-
Notifications
You must be signed in to change notification settings - Fork 6
ERC Testing
Antonio Yang edited this page Oct 14, 2021
·
4 revisions
Once you deploy the contract followed by Deploy Guide
It is easy to test the token contract work fine by javascript.
Create utils.js with contract abi like this, and provide URL for the blockchain network and also two private key for account with currency.
// utils.js
const Web3 = require("web3");
const HDWalletProvider = require('truffle-hdwallet-provider');
const URL = 'http://localhost:8545'; // network you need
const privateKeys = [
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // private key
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', // private key
];
const erc20abi = [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "internalType": "address", "name": "account", "type": "address" }],
"name": "balanceOf",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "recipient", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }],
"name": "transfer",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [{ "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" }],
"name": "allowance",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" }],
"name": "approve",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "sender", "type": "address" },
{ "internalType": "address", "name": "recipient", "type": "address" },
{ "internalType": "uint256", "name": "amount", "type": "uint256" }
],
"name": "transferFrom",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{ "constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
}
];
const erc721abi = [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [{ "internalType": "address", "name": "account", "type": "address" }],
"name": "balanceOf",
"outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "recipient", "type": "address" },
{ "internalType": "uint256", "name": "_tokenId", "type": "uint256" }
],
"name": "transfer",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "_to", "type": "address" },
{ "internalType": "uint256", "name": "_tokenId", "type": "uint256" }
],
"name": "approve",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "sender", "type": "address" },
{ "internalType": "address", "name": "recipient", "type": "address" },
{ "internalType": "uint256", "name": "_tokenId", "type": "uint256" }
],
"name": "transferFrom",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{ "internalType": "string", "name": "", "type": "string" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [{ "name": "_tokenId", "type": "uint256" }],
"name": "ownerOf",
"outputs": [{ "name": "_owner", "type": "address" }],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [ { "name": "_tokenId", "type": "uint256" } ],
"name": "getApproved",
"outputs": [{ "name": "_owner", "type": "address" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "_operator", "type": "address" },
{ "internalType": "bool", "name": "_approved", "type": "bool" }
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "owner", "type": "address" },
{ "internalType": "address", "name": "operator", "type": "address" }
],
"name": "isApprovedForAll",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
];
const erc1155abi = [
{
"inputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"constant": true,
"inputs": [
{ "name": "account", "type": "address" },
{ "name": "token_id", "type": "uint256" }
],
"name": "balanceOf",
"outputs": [
{ "name": "", "type": "uint256" }
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "internalType": "address[]", "name": "account", "type": "address[]" },
{ "internalType": "uint256[]", "name": "account", "type": "uint256[]" }
],
"name": "balanceOfBatch",
"outputs": [
{ "name": "", "type": "uint256[]" }
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256", "name": "token_id", "type": "uint256" },
{ "internalType": "uint256", "name": "value", "type": "uint256" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"name": "safeTransferFrom",
"outputs": [],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": true,
"inputs": [
{ "internalType": "address", "name": "from", "type": "address" },
{ "internalType": "address", "name": "to", "type": "address" },
{ "internalType": "uint256[]", "name": "token_id", "type": "uint256[]" },
{ "internalType": "uint256[]", "name": "value", "type": "uint256[]" },
{ "internalType": "bytes", "name": "data", "type": "bytes" }
],
"name": "safeBatchTransferFrom",
"outputs": [
{ "name": "", "type": "uint256[]" }
],
"payable": false,
"stateMutability": "view",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "_operator", "type": "address" },
{ "internalType": "bool", "name": "_approved", "type": "bool" }
],
"name": "setApprovalForAll",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": false,
"inputs": [
{ "internalType": "address", "name": "owner", "type": "address" },
{ "internalType": "address", "name": "operator", "type": "address" }
],
"name": "isApprovedForAll",
"outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
];
module.exports = {
provider: null,
web3: function () {
this.provider = new HDWalletProvider(privateKeys, URL, 0, privateKeys.length);
return new Web3(this.provider);
},
erc20abi: erc20abi,
erc721abi: erc721abi,
erc1155abi: erc1155abi,
};
Install the dependency of javascript
npm install truffle-hdwallet-provider [email protected]
Modify the contract address that you deployed, then run creating following test script,
and run by node erc20.js
, node erc721.js
or node erc1155.js
// erc20.js
const utils = require('./utils');
(async () => {
const web3 = utils.web3();
let accounts = await web3.eth.getAccounts();
console.log(`accounts: ${JSON.stringify(accounts)}`);
console.log(`${accounts[0]} balance: ${await web3.eth.getBalance(accounts[0])}`);
console.log(`${accounts[1]} balance: ${await web3.eth.getBalance(accounts[1])}`);
// TODO modify contract address after deploy
let contractAddress = "0x17ebaec2e846d0dfff59cd8a6819219517fac610";
let contract = new web3.eth.Contract(utils.erc20abi, contractAddress);
let result;
//////////////////////////////
// check out token parameters
// Demo
result = await contract.methods.name().call();
console.log(result);
console.log(`contract.name() = ${result}`);
// ETD
result = await contract.methods.symbol().call();
console.log(`contract.symbol() = ${result}`);
// 8
result = await contract.methods.decimals().call();
console.log(`contract.decimals() = ${result}`);
// 10000
result = await contract.methods.totalSupply().call();
console.log(`contract.totalSupply() = ${result}`);
//////////////////////////////
// Transfer and check balance
// check erc20 balances
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
let amount = 2;
let allowance = 3;
// transfer
await contract.methods.transfer(accounts[1], amount)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`Transfer ${amount} token from address(${accounts[0]}) to address(${accounts[1]})`);
});
// check erc20 balances
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
//////////////////////////////////////
// Approve other to transfer allowance
await contract.methods.approve(accounts[1], allowance)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`${accounts[0]} approve allowance ${allowance} token for address(${accounts[1]})`);
});
result = await contract.methods.allowance(accounts[0], accounts[1]).call();
console.log(`contract.allowance(${accounts[0]},${accounts[1]}) = ${result}`);
// transfer from
await contract.methods.transferFrom(accounts[0], accounts[1], amount)
.send({ from: accounts[1] })
.on('receipt', function (receipt) {
console.log(`${accounts[1]} transfer ${amount} token from address(${accounts[0]}) to address(${accounts[1]})`);
});
result = await contract.methods.allowance(accounts[0], accounts[1]).call();
console.log(`contract.allowance(${accounts[0]},${accounts[1]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
await utils.provider.engine.stop();
})();
// erc721.js
const utils = require('./utils');
(async () => {
const web3 = utils.web3();
let accounts = await web3.eth.getAccounts();
console.log(`accounts: ${JSON.stringify(accounts)}`);
console.log(`${accounts[0]} balance: ${await web3.eth.getBalance(accounts[0])}`);
console.log(`${accounts[1]} balance: ${await web3.eth.getBalance(accounts[1])}`);
// TODO modify contract address after deploy
let contractAddress = "0x399ffe5505d47ce4917c5d9feb013b5fc0b4db2d";
let contract = new web3.eth.Contract(utils.erc721abi, contractAddress);
let result;
//////////////////////////////
// Transfer and check balance
// check erc20 balances
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
result = await contract.methods.ownerOf(1).call();
console.log(`contract.ownerOf(1) = ${result}`);
result = await contract.methods.ownerOf(2).call();
console.log(`contract.ownerOf(2) = ${result}`);
// transfer
await contract.methods.transfer(accounts[1], 1)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`Transfer token 1 from address(${accounts[0]}) to address(${accounts[1]})`);
});
result = await contract.methods.ownerOf(1).call();
console.log(`contract.ownerOf(1) = ${result}`);
result = await contract.methods.ownerOf(2).call();
console.log(`contract.ownerOf(2) = ${result}`);
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
await contract.methods.approve(accounts[1], 2)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`${accounts[0]} approve token 2 for address(${accounts[1]})`);
});
result = await contract.methods.getApproved(2).call();
console.log(`contract.getApproved(2) = ${result}`);
await contract.methods.transferFrom(accounts[0], accounts[1], 2)
.send({ from: accounts[1] })
.on('receipt', function (receipt) {
console.log(`${accounts[1]} transfer token 2 from address(${accounts[0]}) to address(${accounts[1]})`);
});
result = await contract.methods.ownerOf(2).call();
console.log(`contract.balanceOf(2) = ${result}`);
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
await contract.methods.setApprovalForAll(accounts[1], true)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`${accounts[0]} approve address(${accounts[1]})`);
});
result = await contract.methods.isApprovedForAll(accounts[0], accounts[1]).call();
console.log(`contract.isApprovedForAll(${accounts[0]},${accounts[1]}) = ${result}`);
result = await contract.methods.getApproved(3).call();
console.log(`contract.getApproved(3) = ${result}`);
await contract.methods.transferFrom(accounts[0], accounts[1], 3)
.send({ from: accounts[1] })
.on('receipt', function (receipt) {
console.log(`${accounts[1]} transfer token 3 from address(${accounts[0]}) to address(${accounts[1]})`);
});
result = await contract.methods.ownerOf(3).call();
console.log(`contract.balanceOf(2) = ${result}`);
result = await contract.methods.balanceOf(accounts[0]).call();
console.log(`contract.balanceOf(${accounts[0]}) = ${result}`);
result = await contract.methods.balanceOf(accounts[1]).call();
console.log(`contract.balanceOf(${accounts[1]}) = ${result}`);
await contract.methods.setApprovalForAll(accounts[1], false)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`${accounts[0]} approve address(${accounts[1]})`);
});
result = await contract.methods.isApprovedForAll(accounts[0], accounts[1]).call();
console.log(`contract.isApprovedForAll(${accounts[0]},${accounts[1]}) = ${result}`);
await utils.provider.engine.stop();
})();
// erc1155.js
const utils = require('./utils');
(async () => {
const web3 = utils.web3();
let accounts = await web3.eth.getAccounts();
console.log(`accounts: ${JSON.stringify(accounts)}`);
console.log(`${accounts[0]} balance: ${await web3.eth.getBalance(accounts[0])}`);
console.log(`${accounts[1]} balance: ${await web3.eth.getBalance(accounts[1])}`);
// TODO modify contract address after deploy
let contractAddress = "0xde906e22fbdfba3bed7fb15aa69278e2ed89659c";
let contract = new web3.eth.Contract(utils.erc1155abi, contractAddress);
let result;
result = await contract.methods.balanceOf(accounts[0], 1).call();
console.log(`contract.balanceOf(${accounts[0]}, 1) = ${result}`);
result = await contract.methods.balanceOf(accounts[0], 2).call();
console.log(`contract.balanceOf(${accounts[0]}, 2) = ${result}`);
result = await contract.methods.balanceOf(accounts[0], 3).call();
console.log(`contract.balanceOf(${accounts[0]}, 3) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [1,1]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [2,2]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [3,3]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = ${result}`);
await contract.methods.setApprovalForAll(accounts[1], true)
.send({ from: accounts[0] })
.on('receipt', function (receipt) {
console.log(`${accounts[0]} approve address(${accounts[1]})`);
});
result = await contract.methods.isApprovedForAll(accounts[0], accounts[1]).call();
console.log(`contract.isApprovedForAll(${accounts[0]},${accounts[1]}) = ${result}`);
await contract.methods.safeTransferFrom(accounts[0], accounts[1], 1, 1, [])
.send({ from: accounts[1] })
.on('receipt', function (receipt) {
console.log(`${accounts[1]} transfer token 1 value 1 from ${accounts[0]} to address(${accounts[1]})`);
});
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [1,1]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [2,2]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [3,3]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = ${result}`);
await contract.methods.safeBatchTransferFrom(accounts[0], accounts[1], [2,3], [1,2], [])
.send({ from: accounts[1] })
.on('receipt', function (receipt) {
console.log(`${accounts[1]} transfer token 2 value 1 and token 3 value 2 from ${accounts[0]} to address(${accounts[1]})`);
// console.log(receipt)
});
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [1,1]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [2,2]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = ${result}`);
result = await contract.methods.balanceOfBatch([accounts[0], accounts[1]], [3,3]).call();
console.log(`contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = ${result}`);
await utils.provider.engine.stop();
})();
Check the results Following are the examples for running the tokens test scripts
accounts: ["0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993","0x1cCA28600d7491365520B31b466f88647B9839eC"]
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 balance: 8999976899998221840
0x1cCA28600d7491365520B31b466f88647B9839eC balance: 1763999999999999757311
Demo
contract.name() = Demo
contract.symbol() = ETD
contract.decimals() = 8
contract.totalSupply() = 1000
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 1000
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 0
Transfer 2 token from address(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 998
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 2
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 approve allowance 3 token for address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.allowance(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993,0x1cCA28600d7491365520B31b466f88647B9839eC) = 3
0x1cCA28600d7491365520B31b466f88647B9839eC transfer 2 token from address(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.allowance(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993,0x1cCA28600d7491365520B31b466f88647B9839eC) = 1
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 996
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 4
accounts: ["0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993","0x1cCA28600d7491365520B31b466f88647B9839eC"]
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 balance: 8999976899998087779
0x1cCA28600d7491365520B31b466f88647B9839eC balance: 1785999999999999741690
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 3
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 0
contract.ownerOf(1) = 0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993
contract.ownerOf(2) = 0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993
Transfer token 1 from address(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.ownerOf(1) = 0x1cCA28600d7491365520B31b466f88647B9839eC
contract.ownerOf(2) = 0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 2
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 1
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 approve token 2 for address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.getApproved(2) = 0x1cCA28600d7491365520B31b466f88647B9839eC
0x1cCA28600d7491365520B31b466f88647B9839eC transfer token 2 from address(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.balanceOf(2) = 0x1cCA28600d7491365520B31b466f88647B9839eC
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 1
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 2
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 approve address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.isApprovedForAll(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993,0x1cCA28600d7491365520B31b466f88647B9839eC) = true
contract.getApproved(3) = 0x0000000000000000000000000000000000000000
0x1cCA28600d7491365520B31b466f88647B9839eC transfer token 3 from address(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.balanceOf(2) = 0x1cCA28600d7491365520B31b466f88647B9839eC
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993) = 0
contract.balanceOf(0x1cCA28600d7491365520B31b466f88647B9839eC) = 3
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 approve address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.isApprovedForAll(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993,0x1cCA28600d7491365520B31b466f88647B9839eC) = false
accounts: ["0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993","0x1cCA28600d7491365520B31b466f88647B9839eC","0x6Be02d1d3665660d22FF9624b7BE0551ee1Ac91b"]
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 balance: 4972999999999997532497
0x1cCA28600d7491365520B31b466f88647B9839eC balance: 1999999999999685323
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993, 1) = 1
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993, 2) = 2
contract.balanceOf(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993, 3) = 3
contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = 1,0
contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = 2,0
contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = 3,0
0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 approve address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.isApprovedForAll(0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993,0x1cCA28600d7491365520B31b466f88647B9839eC) = true
0x1cCA28600d7491365520B31b466f88647B9839eC transfer token 1 value 1 from 0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = 0,1
contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = 2,0
contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = 3,0
0x1cCA28600d7491365520B31b466f88647B9839eC transfer token 2 value 1 and token 3 value 2 from 0x8663DBF0cC68AaF37fC8BA262F2df4c666a41993 to address(0x1cCA28600d7491365520B31b466f88647B9839eC)
contract.balanceOfBatch([accounts[0], accounts[1]], [1,1]) = 0,1
contract.balanceOfBatch([accounts[0], accounts[1]], [2,2]) = 1,1
contract.balanceOfBatch([accounts[0], accounts[1]], [3,3]) = 1,2