Created
June 27, 2018 14:38
-
-
Save NoahMarconi/be4213f8147dea60a1ab30db86760828 to your computer and use it in GitHub Desktop.
ABI Encoder Examples
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
pragma solidity ^0.4.24; | |
pragma experimental ABIEncoderV2; | |
contract ABIExample { | |
enum Permission { ReadOnly, Write, Admin } | |
struct User { | |
uint256 id; | |
Permission permission; | |
} | |
User[] users; | |
constructor() public { | |
users.push(User(uint256(111), Permission.Admin)); | |
users.push(User(uint256(222), Permission.Write)); | |
users.push(User(uint256(333), Permission.ReadOnly)); | |
} | |
function getUsers() public constant returns (User[]) { | |
return users; | |
} | |
function getUsersBytes() public constant returns (bytes) { | |
User[] memory allUsers = users; | |
return abi.encode(allUsers); | |
} | |
function set(User newUser) public { | |
users.push(newUser); | |
} | |
} |
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
pragma solidity ^0.4.24; | |
contract Caller { | |
function callExternal(address _to, bytes _data) | |
public | |
returns (bool success) | |
{ | |
assembly { | |
success := call(not(0), _to, 0, add(_data, 0x20), mload(_data), 0, 0) | |
} | |
} | |
} |
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
// The following example is meant to be a simple self contained example. | |
// | |
// To run, paste into a node console and replace `CODE HERE` with your | |
// solidity code. | |
const ethers = require('ethers'); | |
const solc = require('solc'); | |
const ganache = require("ganache-cli"); | |
// Provider / Signer setup. | |
const providers = ethers.providers; | |
const web3Provider = new providers.Web3Provider(ganache.provider({ gasLimit: 6e6 })); | |
const signer = web3Provider.getSigner(); | |
// Compile the code snippets. | |
let contractCode = `ABI EXAMPLE CONTRACT CODE HERE`; // Backticks for multi-line strings. | |
let callerContractCode = `CALLER CONTRACT CODE HERE`; // Backticks for multi-line strings. | |
let compiledContract = solc.compile(contractCode); | |
let callerCompiledContract = solc.compile(callerContractCode); | |
let { interface, bytecode } = compiledContract.contracts[':ABIExample']; | |
let deployTransaction = ethers.Contract.getDeployTransaction('0x' + bytecode, interface); | |
let sendPromise = signer.sendTransaction(Object.assign(deployTransaction, { gas: 6e6 })); | |
// Set up Caller contract deployment. | |
let callerInterface = callerCompiledContract.contracts[':Caller'].interface; | |
let callerBytecode = callerCompiledContract.contracts[':Caller'].bytecode; | |
let deployCallerTransaction = ethers.Contract.getDeployTransaction('0x' + callerBytecode, callerInterface); | |
let callerSendPromise = signer.sendTransaction(Object.assign(deployCallerTransaction, { gas: 6e6 })); |
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
// The following example is meant to be a simple self contained example. | |
// | |
// To run, paste into a node console after having run 1_compile.js. | |
// Set up ABIExample contract deployment. | |
let ABIExample; | |
let userArray; | |
let userBytesArray; | |
sendPromise.then(res => { | |
web3Provider.getTransactionReceipt(res.hash).then(res => { | |
// JS contract interface. | |
ABIExample = new ethers.Contract(res.contractAddress, interface, web3Provider); | |
// Log result of calling the contract's `getUsers()` function. | |
ABIExample.getUsers().then(res => { | |
userArray = res; | |
console.log('\n\n\n\nUser Array: '); | |
console.log(userArray); | |
}); | |
// Log result of calling the contract's `getUsersBytes()` function. | |
ABIExample.getUsersBytes().then(res => { | |
userBytesArray = res; | |
console.log('\n\n\n\n\User Bytes Array: '); | |
console.log(userBytesArray); | |
}); | |
}); | |
}); |
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
// The following example is meant to be a simple self contained example. | |
// | |
// To run, paste into a node console after having run 2_read.js. | |
let usersArrayType = ["tuple(uint256,uint8)[]"]; | |
let decodedData = ethers.utils.AbiCoder.defaultCoder.decode(usersArrayType, userBytesArray); | |
console.log(decodedData); | |
// Or to print nicer decodedData[0].forEach(x => console.log(`id -> ${x[0]} permission -> ${x[1]}`)); | |
// Or if you have the abi the following would work as well. | |
usersArrayType = [{"components":[{"name":"id","type":"uint256"},{"name":"permission","type":"uint8"}],"name":"","type":"tuple[]"}] | |
decodedData = ethers.utils.AbiCoder.defaultCoder.decode(usersArrayType, userBytesArray); | |
console.log(decodedData); |
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
// The following example is meant to be a simple self contained example. | |
// | |
// To run, paste into a node console after having run 2_read.js. | |
sendPromise.then(res => { | |
web3Provider.getTransactionReceipt(res.hash).then(res => { | |
// New JS contract interface. | |
ABIExample = new ethers.Contract(res.contractAddress, interface, signer); | |
// Update state with User(444, Permission.Admin). | |
ABIExample.set({ id: 444, permission: 2 }, { gasLimit: 2e5 }).then(function(transaction) { | |
// Get the users array again to see the new `User` persisted. | |
ABIExample.getUsers().then(res => { | |
// Log the result. | |
userArray = res; | |
console.log('\n\n\n\n\User Bytes Array with Additional User: '); | |
console.log(userArray); | |
}); | |
}); | |
}); | |
}); |
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
// The following example is meant to be a simple self contained example. | |
// | |
// To run, paste into a node console after having run 2_read.js. | |
let userType = ["tuple(uint256,uint8)"]; | |
let inputData = [ // AbiCoder wraps all of the data. | |
[ // User tuple. | |
555, // uint256 representing `id`. | |
0, // uint256 representing `permission`. | |
] | |
]; | |
// Missing function sig prefix. | |
let encodedData = ethers.utils.AbiCoder.defaultCoder.encode(userType, inputData); | |
// Includes prefix using ethers.js and our contract interface. | |
encodedData = ABIExample.interface.functions.set({ id: 555, permission: 0 }).data; | |
let Caller; | |
callerSendPromise.then(res => { | |
web3Provider.getTransactionReceipt(res.hash).then(res => { | |
// New JS contract interface. | |
Caller = new ethers.Contract(res.contractAddress, callerInterface, signer); | |
// Update state with User(555, Permission.ReadOnly). | |
Caller.callExternal(ABIExample.address, encodedData, { gasLimit: 2e5 }).then(res => { | |
// Get the users array again to see the new `User` persisted. | |
ABIExample.getUsers().then(res => { | |
// Log result. | |
userArray = res; | |
console.log('\n\n\n\n\User Bytes Array with Additional User: '); | |
console.log(userArray); | |
}); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment