Skip to content
This repository has been archived by the owner on Sep 19, 2024. It is now read-only.

Commit

Permalink
added transferFrom, approvals todo
Browse files Browse the repository at this point in the history
  • Loading branch information
erhant committed Oct 14, 2023
1 parent 7746148 commit 88b5075
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 42 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ broadcast

# Python
__pycache__

# VSCODE
.vscode
3 changes: 3 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"printWidth": 120
}
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,11 @@ You can use the following commands for testing.
```sh
# run all tests
forge test -vvv
forge t -vvv
# run a specific test
forge test -vvv --mc PolynomialTest
forge test -vvv --mc Huffd1Test
forge t -vvv --mc Polynomial
forge t -vvv --mc Huffd1
```
I use `-vvv` to see reverts in detail.
Expand Down
83 changes: 53 additions & 30 deletions src/Huffd1.huff
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,29 @@
///////////////////////////////////////////////////////////////////////////////
//// STORAGE ////
///////////////////////////////////////////////////////////////////////////////
#define constant BAL_SLOT = 0xbabe69babe69babe69babe69babe69 // balances
// #define constant APV_SLOT = 0xface42face42face42face42face42 // approvals

/// @dev Starting slot of the ownership polynomial in reverse coefficient form.
#define constant OWN_SLOT = 0xbabe69babe69babe69babe69babe69

/// @dev Starting slot of the approval polynomial in reverse coefficient form.
#define constant APV_SLOT = 0xface42face42face42face42face42

///////////////////////////////////////////////////////////////////////////////
//// MACROS ////
///////////////////////////////////////////////////////////////////////////////

/// @dev Utility function to SLOAD a polynomial at a storage slot
/// to the memory at the given memory slot.
#define macro LOAD_POLY(slot) = takes (1) returns (2) {
// input: [m] (memoryOffset)
<slot> // [m, s] (storageSlot)
swap1 // [s, m]
[TOTAL_SUPPLY] // [s, m, l] (length)
POLY_SLOAD() // [m, l]
// output; [m, l] (memoryOffset, length)
}

/// @dev Returns the string "Huffd1".
#define macro NAME() = takes (0) returns (0) {
0x20 0x00 mstore // offset
0x06 0x20 mstore // length (12 hex chars, 6 bytes)
Expand All @@ -56,6 +73,7 @@
0x60 0x00 return
}

/// @dev Returns the symbol "FFD1".
#define macro SYMBOL() = takes (0) returns (0) {
0x20 0x00 mstore // offset
0x04 0x20 mstore // length (8 hex chars, 4 bytes)
Expand All @@ -66,36 +84,36 @@

#define macro OWNER_OF() = takes (1) returns (1) {
// input: [t] (tokenId)
[BAL_SLOT] // [t, s] (storageSlot)
0x00 // [t, s, m] (memoryOffset)
[TOTAL_SUPPLY] // [t, s, m, l] (length)
POLY_SLOAD() // [t, m, l]
0x00 // [t, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, m, l]
dup3 // [t, m, l, t] (token id)
POLY_EVAL(ORDER) // [t, m, l, a] (address)
swap3 // [a, m, l, t]
pop pop pop // [a]
// output: [a] (owner)
}

#define macro TRANSFER() = takes (3) returns (0) {
#define macro TRANSFER_FROM() = takes (3) returns (0) {
// input: // [t, b, a] (token, to, from)

// assert that token is owner by caller
// assert that token is owned by `from`
dup3 OWNER_OF() // [t, b, a, o] (owner of t)
dup2 eq // [t, b, a, a == o]
success jumpi

// OR, assert that token is approved to `to`
// TODO: implement

0x00 0x00 revert
success:

// find scale amount
[ORDER] sub // [t, b, -a] (-a = p - a) in field
add // [t, v] (v := b - a)

// load balance polynomial
[BAL_SLOT] // [t, v, s] (storageSlot)
0x00 // [t, v, s, mP] (memoryOffset)
[TOTAL_SUPPLY] // [t, v, s, mP, l] (length)
POLY_SLOAD() // [t, v, mP, l]
// load ownership polynomial
0x00 // [t, v, mP] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [t, v, mP, l]

// load basis polynomial
__tablestart(Basis) // [t, v, mP, l, c]
Expand All @@ -104,11 +122,10 @@
// [t, v, mP, l, c, o]
add // [t, v, mP, l, c] (codeOffset)
[COEFF_SIZE] // [t, v, mP, l, c, s] (coefficient size)
dup4 // [t, v, mP, l, c, s, mP]
dup4 // [t, v, mP, l, c, s, mP, l] (length)
dup4 dup4 // [t, v, mP, l, c, s, mP, l]
0x20 mul // [t, v, mP, l, c, s, mP, l'] (l' := l * 32)
add // [t, v, mP, l, c, s, mQ] (memory offset)
dup4 // [t, v, mP, l, c, s, mQ, l] (length)
dup4 // [t, v, mP, l, c, s, mQ, l]
POLY_CODECOPY() // [t, v, mP, l, mQ, l]
pop swap1 // [t, v, mP, mQ, l]

Expand All @@ -120,19 +137,17 @@
POLY_ADD(ORDER) // [t, v, mP, l]

// store the new polynomial
[BAL_SLOT] swap1 // [t, v, mP, sQ, l]
[OWN_SLOT] swap1 // [t, v, mP, sQ, l]
POLY_SSTORE() // [t, v, sQ, l]
pop pop pop pop // []
}

#define macro BALANCE_OF() = takes (1) returns (1) {
// input: // [a] (address)

// load balance polynomial once at the start
[BAL_SLOT] // [a, $] (storageSlot)
0x00 // [a, $, m] (memoryOffset)
[TOTAL_SUPPLY] // [a, $, m, l] (length)
POLY_SLOAD() // [a, m, l]
// load ownership polynomial once at the start
0x00 // [a, m] (memoryOffset)
LOAD_POLY(OWN_SLOT) // [a, m, l]

0x00 // [a, m, l, s] (total balance initially 0)
swap1 // [a, m, s, l]
Expand Down Expand Up @@ -171,7 +186,8 @@

pop // [a, m, s, l]
pop // [a, m, s]
swap1 // [s, a]
swap2 // [s, m, a]
pop // [s, m]
pop // [s]
// output: // [s] (total balance)
}
Expand All @@ -185,17 +201,18 @@
// the constant polynomial equal to OWNER will result
// in all tokens being owned by that OWNER
[OWNER] sload // [owner]
[BAL_SLOT] sstore // []
[OWN_SLOT] sstore // []
}

#define macro HUFFD1_MAIN() = takes (1) returns (1) {
OWNED_MAIN()

dup1 __FUNC_SIG(name) eq name jumpi
dup1 __FUNC_SIG(symbol) eq symbol jumpi
dup1 __FUNC_SIG(ownerOf) eq ownerOf jumpi
dup1 __FUNC_SIG(transfer) eq transfer jumpi
dup1 __FUNC_SIG(balanceOf) eq balanceOf jumpi
dup1 __FUNC_SIG(name) eq name jumpi
dup1 __FUNC_SIG(symbol) eq symbol jumpi
dup1 __FUNC_SIG(ownerOf) eq ownerOf jumpi
dup1 __FUNC_SIG(transfer) eq transfer jumpi
dup1 __FUNC_SIG(balanceOf) eq balanceOf jumpi
dup1 __FUNC_SIG(transferFrom) eq transferFrom jumpi
no_match jump

name:
Expand All @@ -211,7 +228,13 @@
0x24 calldataload // [t] (tokenId)
0x04 calldataload // [t, b] (to address)
caller // [t, b, a] (from address)
TRANSFER() // []
TRANSFER_FROM() // []
0x00 0x00 return // []
transferFrom:
0x44 calldataload // [t] (tokenId)
0x24 calldataload // [t, b] (to address)
0x04 calldataload // [t, b, a] (from address)
TRANSFER_FROM() // []
0x00 0x00 return // []
balanceOf:
0x04 calldataload // [a] (address)
Expand Down
39 changes: 30 additions & 9 deletions test/Huffd1.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ contract Huffd1Test is Test {
/// @dev Set-up to run before each test.
function setUp() public {
string memory code = vm.readFile("src/test/Huffd1.t.huff");
huffd1 = Huffd1(
HuffDeployer.deploy_with_code_args(
"Huffd1",
code,
abi.encode(OWNER)
)
);
huffd1 = Huffd1(HuffDeployer.deploy_with_code_args("Huffd1", code, abi.encode(OWNER)));
}

/// @dev Should return correct name and symbol.
Expand Down Expand Up @@ -62,12 +56,37 @@ contract Huffd1Test is Test {
}
}

/// @dev Should transfer tokens correctly.
function test_TransferFrom() public {
for (uint256 tokenId = 0; tokenId < TOTAL_SUPPLY; ++tokenId) {
// owner --> new owner
address NEW_OWNER = address(0x9);
vm.prank(OWNER);
huffd1.transferFrom(OWNER, NEW_OWNER, tokenId);
assertEq(huffd1.ownerOf(tokenId), NEW_OWNER);

// new owner -> another new owner
address NEW_NEW_OWNER = address(0x6);
vm.prank(NEW_OWNER);
huffd1.transferFrom(NEW_OWNER, NEW_NEW_OWNER, tokenId);
assertEq(huffd1.ownerOf(tokenId), NEW_NEW_OWNER);
}
}

/// @dev Should fail to transfer a not-owned token.
function testFail_Transfer() public {
vm.prank(address(0x5)); // not an owner
function testFail_Transfer_NotOwner() public {
address NOT_OWNER = address(0x5);
vm.prank(NOT_OWNER);
huffd1.transfer(OWNER, 0);
}

/// @dev Should fail to transferFrom a not-owned token.
function testFail_TransferFrom_NotOwner() public {
address NOT_OWNER = address(0x5);
vm.prank(NOT_OWNER); // not an owner
huffd1.transferFrom(NOT_OWNER, NOT_OWNER, 0);
}

/// @dev Should give corect balance.
function test_BalanceOf() public {
assertEq(huffd1.balanceOf(OWNER), TOTAL_SUPPLY);
Expand Down Expand Up @@ -106,4 +125,6 @@ interface Huffd1 is Owned {
function balanceOf(address owner) external view returns (uint256 balance);

function transfer(address to, uint256 tokenId) external;

function transferFrom(address from, address to, uint256 tokenId) external;
}
4 changes: 4 additions & 0 deletions test/Polynomial.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,14 @@ contract PolynomialTest is Test {

interface IPolynomial {
function eval(uint256 basis, uint256 point) external view returns (uint256 evaluation);

function addEval(uint256 basis1, uint256 basis2, uint256 point) external view returns (uint256 evaluation);

function scaleEval(uint256 basis, uint256 scale, uint256 point) external view returns (uint256 evaluation);

function evalStore(uint256 point) external view returns (uint256 evaluation);

function addStore(uint256 basis) external;

function scaleStore(uint256 scale) external;
}

0 comments on commit 88b5075

Please sign in to comment.