Skip to content
This repository has been archived by the owner on Jul 4, 2022. It is now read-only.

transfer_From added but tests failiing #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 65 additions & 3 deletions examples/erc20/contracts/ERC20.huff
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,20 @@
0x20 0x00 return
}

#define macro _ALLOWANCE() = takes (2) returns (1) {
// call stack [from,to]
LOAD_ELEMENT_FROM_KEYS(0x00) // [value]

0x00 mstore

0x20 0x00 return
}

#define macro ALLOWANCE() = takes (0) returns (0) {
0x24 calldataload // [to]
0x04 calldataload // [from, to]

LOAD_ELEMENT_FROM_KEYS(0x00) // [value]
_ALLOWANCE() // [value]

0x00 mstore

Expand Down Expand Up @@ -94,12 +103,17 @@
[BALANCE_LOCATION] STORE_ELEMENT_FROM_KEYS(0x00) // [value, from, to]
}

#define macro _APPROVE() = takes (2) returns (0) {
// call stack [from, to , value]
STORE_ELEMENT_FROM_KEYS(0x00)
}

#define macro APPROVE() = takes (0) returns (0) {
0x24 calldataload // [value]
0x04 calldataload // [to, value]
caller // [from, to, value]

STORE_ELEMENT_FROM_KEYS(0x00)
_APPROVE()
}

#define macro TRANSFER() = takes(0) returns(1) {
Expand Down Expand Up @@ -127,6 +141,52 @@
0x00 0x00 revert
}

#define macro TRANSFER_FROM() = takes (0) returns (0) {
0x04 calldataload // [from]
0x24 calldataload // [to, from]
0x44 calldataload // [value, to, from]

dup2 // [to, value, to, from]
dup4 // [from, to, value, to, from]

// check if allowance > value
_ALLOWANCE() // [allowance, value, to, from]
dup2 // [value, allowance, value, to, from]
dup2 // [allowance, value, allowance, value, to, from]
lt // [allowance < value, allowance, value, to, from]

// revert if allowance < value
error jumpi // [allowance, value, to, from]

// update allowance
sub // [allowance-value, to, from]
swap2 // [from, to, value]
dup3 // [value,from,to,value]
dup3 // [to,value,from,to,value]
dup3 // [from,to,value,from,to,value]
_APPROVE() // [from,to,value]

transfer value
swap1 // [to,from,value]
swap2 // [value,from,to]
TRANSFER_TAKE_FROM(error) // [value, from, to]
TRANSFER_GIVE_TO() // [value, from, to]

// Emit the transfer event.
// 0x00 mstore // [from, to]
// [TRANSFER_EVENT_SIGNATURE] // [sig, from, to]
// 0x20 0x00 // [0, 32, sig, from, to]
// log3 // []

// Return "1" to represent a succesful transfer.
0x01 0x00 mstore
0x20 0x00 return

// Error destination.
error:
0x00 0x00 revert
}

/* Mint Functions */
#define macro MINT() = takes(0) returns (0) {
// Ensure that the sender is the owner of the contract.
Expand Down Expand Up @@ -158,13 +218,16 @@
#define macro MAIN() = takes(0) returns (0) {
// Identify which function is being called.
0x00 calldataload 0xE0 shr
dup1 0x23b872dd eq transferFrom jumpi
dup1 0xa9059cbb eq transfer jumpi
dup1 0x40c10f19 eq mints jumpi
dup1 0x70a08231 eq balanceOf jumpi
dup1 0x18160ddd eq totalSupply jumpi
dup1 0x095ea7b3 eq approve jumpi
dup1 0xdd62ed3e eq allowance jumpi

transferFrom:
TRANSFER_FROM()
transfer:
TRANSFER()
mints:
Expand All @@ -177,5 +240,4 @@
APPROVE()
allowance:
ALLOWANCE()

}
2 changes: 1 addition & 1 deletion examples/erc20/contracts/utils/HashMap.huff
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
sstore // []
}

#define macro STORE_ELEMENT_FROM_KEYS(mem_ptr) = takes(2) returns (0) {
#define macro STORE_ELEMENT_FROM_KEYS(mem_ptr) = takes(3) returns (0) {
// Input stack: [key1, key2, value]
GET_SLOT_FROM_KEYS(<mem_ptr>) // [slot, value]
sstore // []
Expand Down
23 changes: 23 additions & 0 deletions examples/erc20/test/erc20.t.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,27 @@ describe("ERC20", () => {

expect(newAllowance).to.equal(val);
});

it("transfer from test", async () => {
await token.mint(owner, val);
// must fail without approval
// await expect(token.transferFrom(owner, user, 1)).to.be.reverted;

await token.approve(user, val);

let oldAllowance = await token.allowance(owner, user);

expect(oldAllowance).to.equal(val);

const toTransfer = val / 50;
// must succeed with half of val
await token.transferFrom(owner, user, val);

// allowance must get reduced
let newAllowance = await token.allowance(owner, user);
expect(newAllowance).to.equal(0);

// let userBal = await token.balanceOf(user);
// expect(userBal).to.equal(toTransfer);
});
});
Loading