Skip to content

Instantly share code, notes, and snippets.

@chriseth
Created December 19, 2017 15:30
Show Gist options
  • Save chriseth/58ce6a037afa0a6db207391792619265 to your computer and use it in GitHub Desktop.
Save chriseth/58ce6a037afa0a6db207391792619265 to your computer and use it in GitHub Desktop.
MyToken - IULIA example
contract MyToken {
function MyToken() {
assembly {
// Store the creator at storage slot zero
sstore(0, caller())
}
}
function () payable {
assembly {
// Protection against sending Ether
if gt(callvalue(), 0) { revert(0, 0) }
// Dispatcher
switch selector()
case 0x70a08231 /* "balanceOf(address)" */ {
returnUint(balanceOf(decodeAsAddress(0)))
}
case 0x18160ddd /* "totalSupply()" */ {
returnUint(totalSupply())
}
case 0xa9059cbb /* "transfer(address,uint256)" */ {
transfer(decodeAsAddress(0), decodeAsUint(1))
}
case 0x40c10f19 /* "mint(address,uint256)" */ {
mint(decodeAsAddress(0), decodeAsUint(1))
}
default {
revert(0, 0)
}
function mint(account, amount) {
if iszero(calledByOwner()) { revert(0, 0) }
mintTokens(amount)
addToBalance(account, amount)
}
function transfer(to, amount) {
deductFromBalance(caller(), amount)
addToBalance(to, amount)
}
/* ---------- calldata decoding functions ----------- */
function selector() -> s {
s := div(calldataload(0), 0x100000000000000000000000000000000000000000000000000000000)
}
function decodeAsAddress(offset) -> v {
v := decodeAsUint(offset)
if iszero(iszero(and(v, not(0xffffffffffffffffffffffffffffffffffffffff)))) {
revert(0, 0)
}
}
function decodeAsUint(offset) -> v {
v := calldataload(add(4, mul(offset, 0x20)))
}
/* ---------- calldata encoding functions ---------- */
function returnUint(v) {
mstore(0, v)
return(0, 0x20)
}
/* -------- storage access ---------- */
function owner() -> o {
o := sload(0)
}
function totalSupply() -> supply {
supply := sload(1)
}
function mintTokens(amount) {
sstore(1, safeAdd(totalSupply(), amount))
}
function accountToStorageOffset(account) -> offset {
offset := add(0x1000, account)
}
function balanceOf(account) -> bal {
bal := sload(accountToStorageOffset(account))
}
function addToBalance(account, amount) {
let offset := accountToStorageOffset(account)
sstore(offset, safeAdd(sload(offset), amount))
}
function deductFromBalance(account, amount) {
let offset := accountToStorageOffset(account)
let bal := sload(offset)
if lt(bal, amount) { revert(0, 0) }
sstore(offset, sub(bal, amount))
}
/* ---------- utility functions ---------- */
function safeAdd(a, b) -> r {
r := add(a, b)
if or(lt(r, a), lt(r, b)) { revert(0, 0) }
}
function calledByOwner() -> cbo {
cbo := eq(owner(), caller())
}
}
}
}
interface ERC20 {
function totalSupply() constant returns (uint totalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function mint(address _addr, uint _value) returns (bool success);
function transfer(address _to, uint _value) returns (bool success);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment