Skip to content

Instantly share code, notes, and snippets.

@clar
Created November 26, 2019 09:43
Show Gist options
  • Save clar/d1fc29850e2457da02aa9a935fdad640 to your computer and use it in GitHub Desktop.
Save clar/d1fc29850e2457da02aa9a935fdad640 to your computer and use it in GitHub Desktop.
const assert = require('assert');
const leftPad = require('left-pad');
const truffleAssert = require('truffle-assertions');
const AccountStorage = artifacts.require("AccountStorage");
const LogicManager = artifacts.require("LogicManager");
const TransferLogic = artifacts.require("TransferLogic");
const BaseAccount = artifacts.require("Account");
const MyToken = artifacts.require("MyToken");
const MyNft = artifacts.require("MyNft");
const BaseAccountProxy = artifacts.require("AccountProxy");
let accountStorage;
let accountLogic;
let transferLogic;
let logicManager;
let baseAccountProxy;
let baseAccountProxy2;
let baseAccount;
let baseAccount2;
let mgrOwner;
let account0;
let account1;
let account2;
let account3;
let instance;
// web3.setProvider(new web3.providers.WebsocketProvider('http://127.0.0.1:7545'));
contract("TransferLogic", accounts => {
before(async () => {
account0 = accounts[0];
account1 = accounts[1];
account2 = accounts[2];
account3 = accounts[3];
accountStorage = await AccountStorage.deployed();
transferLogic = await TransferLogic.deployed();
logicManager = await LogicManager.deployed();
myToken = await MyToken.deployed();
myNft = await MyNft.deployed();
baseAccountImp = await BaseAccount.deployed();
baseAccountProxy = await BaseAccountProxy.new(baseAccountImp.address);
baseAccount = await BaseAccount.at(baseAccountProxy.address)
// baseAccount = await BaseAccount.new();
instance = await new web3.eth.Contract(transferLogic.abi, transferLogic.address);
// instance.events.allEvents({
// filter: {},
// fromBlock: 0
// }, (error, event) => { console.log(event); });
await baseAccount.init(logicManager.address, accountStorage.address, [transferLogic.address], [account1, account2], [])
//(address to, uint amount)
await myToken.mint(baseAccount.address, 10000);
await myToken.mint(account3, 10000);
await myToken.approve(baseAccount.address, 500, {from:account3});
//(address to, uint tokenId)
await myNft.mint(baseAccount.address, 123);
await myNft.mint(account3, 456);
await myNft.approve(baseAccount.address, 456, {from:account3});
// truffleAssert.eventEmitted(tx, 'AccountInit', (ev) => {
// console.log(ev)
// return ev//.h === funcHash//bettingAccount && ev.betNumber.eq(ev.winningNumber);
// });
// truffleAssert.eventEmitted(tx, 'EnabledStaticCall', (ev) => {
// console.log(ev)
// return ev//.h === funcHash//bettingAccount && ev.betNumber.eq(ev.winningNumber);
// });
mgrOwner = await logicManager.owner();
console.log("accountstorage:", accountStorage.address);
console.log("transferLogic:", transferLogic.address);
console.log("logicManager:", logicManager.address);
console.log("mgrOwner:", mgrOwner);
console.log("baseAccount:", baseAccount.address);
console.log("mytoken:", myToken.address);
console.log("mynft:", myNft.address);
});
it('check current logics of logicManager', async () => {
const a = await logicManager.authorized(transferLogic.address);
assert.equal(a, true, "Current logic not correct.");
});
it('check manager of BaseAccount', async () => {
const mgr = await baseAccount.manager();
assert.equal(mgr, logicManager.address, "The mgr of baseAccount is not correct.");
});
it('create account', async () => {
var keys = [account2,account3];
baseAccountProxy2 = await BaseAccountProxy.new(baseAccountImp.address);
baseAccount2 = await BaseAccount.at(baseAccountProxy2.address)
// baseAccount2 = await BaseAccount.new();
await baseAccount2.init(logicManager.address, accountStorage.address, [transferLogic.address], keys, [])
var pk0 = await accountStorage.getKeyData(baseAccount2.address, 0);//.call();
var pk1 = await accountStorage.getKeyData(baseAccount2.address, 1);//.call();
// console.log("baseAccount2:", baseAccount2.address);
// console.log("pk0:",pk0);
// console.log("pk1:",pk1);
assert.equal(pk0, keys[0], "account created with incorrect pubkey address 0.");
assert.equal(pk1, keys[1], "account created with incorrect pubkey address 1.");
});
it('transfer eth', async () => {
var pk1 = await accountStorage.getKeyData(baseAccount.address, 1);
let toAddr = account2;
let signingKey = pk1;
let nonce = await getNonce();//32;
let amount = 800 // 800 wei
let data = web3.eth.abi.encodeFunctionCall({
name: 'transferEth',
type: 'function',
inputs: [{
type: 'address',
name: 'from'
},{
type: 'address',
name: 'to'
},{
type: 'uint256',
name: 'amount'
}]
}, [baseAccount.address, toAddr, amount]);
let msg = '0x1900' + transferLogic.address.slice(2) + data.slice(2) + pad(nonce.toString('16')).slice(2);
let hash = web3.utils.soliditySha3(msg);
console.log('msg:', msg)
console.log('hash:', hash);
console.log('signingKey:', signingKey)
console.log('hash len', hash.length)
// console.log('address1:', account1);
// console.log('address2:', account2);
let sig = await web3.eth.sign(hash, signingKey);
sig = fixSignature(sig);
console.log("sig:", sig)
await web3.eth.sendTransaction({from:account0, to:baseAccount.address, value:1000});
let testmsg = 'Some data'
let testhash = web3.utils.soliditySha3(testmsg);
let testsig = await web3.eth.sign(testhash, signingKey);
console.log('testmsg:', testmsg)
console.log('testhash:', testhash)
console.log('testsig:', testsig)
var before = await web3.eth.getBalance(baseAccount.address);
assert.equal(before, 1000, "baseAccount balance before should be 1000 wei")
// let tx = await transferLogic.enter(data, sig, nonce);//.send({ from: owner });
// var after = await web3.eth.getBalance(baseAccount.address)
// assert.equal(after, 200, "baseAccount balance after should be 200 wei")
// assert.equal(before - after, amount, "eth transfer failed.");
instance.methods.enter(data, sig, nonce).estimateGas(function(err, gas){
console.log("gas : ", gas);
});
});
it('check erc20 token direct transfer', async () => {
var pk1 = await accountStorage.getKeyData(baseAccount.address, 1);
let nonce = await getNonce();//64;
let signingKey = pk1;
let toAddr = account2;
let amount = '100'; // 100 MTK
let sendData = web3.eth.abi.encodeFunctionCall({
name: 'transferErc20',
type: 'function',
inputs: [{
type: 'address',
name: 'from'
},{
type: 'address',
name: 'to'
},{
type: 'address',
name: 'token'
},{
type: 'uint256',
name: 'amount'
}]
}, [baseAccount.address, toAddr, myToken.address, amount]);
let msg = '0x1900' + transferLogic.address.slice(2) + sendData.slice(2) + pad(nonce.toString('16')).slice(2);
let hash = web3.utils.soliditySha3(msg);
// console.log('hash:', hash);
// console.log('address1:', account1);
// console.log('address2:', account2);
let sig = await web3.eth.sign(hash,signingKey);
sig = fixSignature(sig);
const balanceBefore = await myToken.balanceOf(baseAccount.address);
// console.log(balanceBefore + " MTK");
await transferLogic.enter(sendData, sig, nonce);
const balanceAfter = await myToken.balanceOf(baseAccount.address);
// console.log(balanceAfter + " MTK");
assert.equal(balanceBefore-balanceAfter, amount, "erc20 token transfer failed.");
});
it('check erc20 token approved transfer', async () => {
var pk1 = await accountStorage.getKeyData(baseAccount.address, 1);
let nonce = await getNonce();//64;
let signingKey = pk1;
let toAddr = account2;
let amount = '100'; // 100 MTK
let sendData = web3.eth.abi.encodeFunctionCall({
name: 'transferApprovedErc20',
type: 'function',
inputs: [{
type: 'address',
name: 'approvedSpender'
},{
type: 'address',
name: 'from'
},{
type: 'address',
name: 'to'
},{
type: 'address',
name: 'token'
},{
type: 'uint256',
name: 'amount'
}]
}, [baseAccount.address, account3, toAddr, myToken.address, amount]);
let msg = '0x1900' + transferLogic.address.slice(2) + sendData.slice(2) + pad(nonce.toString('16')).slice(2);
let hash = web3.utils.soliditySha3(msg);
// console.log('hash:', hash);
// console.log('address1:', account1);
// console.log('address2:', account2);
let sig = await web3.eth.sign(hash,signingKey);
sig = fixSignature(sig);
const balanceBefore = await myToken.balanceOf(account3);
// console.log(balanceBefore + " MTK");
await transferLogic.enter(sendData, sig, nonce);
const balanceAfter = await myToken.balanceOf(account3);
// console.log(balanceAfter + " MTK");
assert.equal(balanceBefore-balanceAfter, amount, "erc20 token approved transfer failed.");
});
it('check erc721 token transfer', async () => {
var pk1 = await accountStorage.getKeyData(baseAccount.address, 1);
let nonce = await getNonce();//65;
let signingKey = pk1;
let toAddr = baseAccount2.address;//account2;
let tokenId = '123';
let emptyBytes = [];
let safe = false;//true;
let sendData = web3.eth.abi.encodeFunctionCall({
name: 'transferNft',
type: 'function',
inputs: [{
type: 'address',
name: 'from'
},{
type: 'address',
name: 'to'
},{
type: 'address',
name: 'nftContract'
},{
type: 'uint256',
name: 'tokenId'
},{
type: 'bytes',
name: 'data'
},{
type: 'bool',
name: 'safe'
}]
}, [baseAccount.address, toAddr, myNft.address, tokenId, emptyBytes, safe]);
let msg = '0x1900' + transferLogic.address.slice(2) + sendData.slice(2) + pad(nonce.toString('16')).slice(2);
let hash = web3.utils.soliditySha3(msg);
// console.log('hash:', hash);
// console.log('address1:', account1);
// console.log('address2:', account2);
let sig = await web3.eth.sign(hash,signingKey);
sig = fixSignature(sig);
const ownerBefore = await myNft.ownerOf(tokenId);
// console.log(ownerBefore);
let tx = await transferLogic.enter(sendData, sig, nonce);
// truffleAssert.eventEmitted(tx, 'ERC721Received', (ev) => {
// console.log(ev)
// return true//.h === funcHash//bettingAccount && ev.betNumber.eq(ev.winningNumber);
// });
const ownerAfter = await myNft.ownerOf(tokenId);
// console.log(ownerAfter);
assert.equal(ownerAfter, toAddr, "erc721 token transfer failed.");
});
it('check erc721 token approved transfer', async () => {
var pk1 = await accountStorage.getKeyData(baseAccount.address, 1);
let nonce = await getNonce();//65;
let signingKey = pk1;
let toAddr = baseAccount2.address;//account2;
let tokenId = '456';
let emptyBytes = [];
let safe = false;//true;
let sendData = web3.eth.abi.encodeFunctionCall({
name: 'transferApprovedNft',
type: 'function',
inputs: [{
type: 'address',
name: 'approvedSpender'
},{
type: 'address',
name: 'from'
},{
type: 'address',
name: 'to'
},{
type: 'address',
name: 'nftContract'
},{
type: 'uint256',
name: 'tokenId'
},{
type: 'bytes',
name: 'data'
},{
type: 'bool',
name: 'safe'
}]
}, [baseAccount.address, account3, toAddr, myNft.address, tokenId, emptyBytes, safe]);
let msg = '0x1900' + transferLogic.address.slice(2) + sendData.slice(2) + pad(nonce.toString('16')).slice(2);
let hash = web3.utils.soliditySha3(msg);
// console.log('hash:', hash);
// console.log('address1:', account1);
// console.log('address2:', account2);
let sig = await web3.eth.sign(hash,signingKey);
sig = fixSignature(sig);
const ownerBefore = await myNft.ownerOf(tokenId);
// console.log(ownerBefore);
let tx = await transferLogic.enter(sendData, sig, nonce);
// truffleAssert.eventEmitted(tx, 'ERC721Received', (ev) => {
// console.log(ev)
// return true//.h === funcHash//bettingAccount && ev.betNumber.eq(ev.winningNumber);
// });
const ownerAfter = await myNft.ownerOf(tokenId);
// console.log(ownerAfter);
assert.equal(ownerAfter, toAddr, "erc721 token approved transfer failed.");
});
})
async function getNonce() {
// let blockNum = await web3.eth.getBlockNumber();
// let num = web3.eth.abi.encodeParameter('uint256',blockNum);
// // console.log(num.slice(34));
// let block = await web3.eth.getBlock(blockNum);
// let ts = web3.eth.abi.encodeParameter('uint256', block.timestamp);
// // console.log(ts.slice(34));
// let n = '0x' + num.slice(34) + ts.slice(34);
// return n;
// await sleep(1);
return web3.eth.abi.encodeParameter('uint256', Math.floor(Date.now()*1000));
}
function fixSignature (signature) {
// in geth its always 27/28, in ganache its 0/1. Change to 27/28 to prevent
// signature malleability if version is 0/1
// see https://github.com/ethereum/go-ethereum/blob/v1.8.23/internal/ethapi/api.go#L465
let v = parseInt(signature.slice(130, 132), 16);
if (v < 27) {
v += 27;
}
const vHex = v.toString(16);
return signature.slice(0, 130) + vHex;
}
//Left packs a (hex) string. Should probably use leftpad
function pad(n) {
assert.equal(typeof(n), 'string', "Passed in a non string")
let data
if (n.startsWith("0x")) {
data = '0x' + leftPad(n.slice(2), '64', '0')
assert.equal(data.length, 66, "packed incorrectly")
return data;
} else {
data = '0x' + leftPad(n, '64', '0')
assert.equal(data.length, 66, "packed incorrectly")
return data;
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment