Created
November 26, 2019 09:43
-
-
Save clar/d1fc29850e2457da02aa9a935fdad640 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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