Skip to content
This repository was archived by the owner on Aug 20, 2024. It is now read-only.
Merged
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
32 changes: 16 additions & 16 deletions src/main.etk
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,29 @@
#
# This is an implementation of EIP-4788's predeploy contract. It implements two
# ring buffers to create bounded beacon root lookup. The first ring buffer is a
# timestamp % rootmod -> timestamp mapping. This is used to ensure timestamp
# timestamp % buflen -> timestamp mapping. This is used to ensure timestamp
# argument actually matches the stored root and isn't different dividend. The
# second ring buffer store the beacon root. It's also keyed by timestamp %
# rootmod and the shifted right by rootmod so the two don't overlap.
# buflen and the shifted right by buflen so the two don't overlap.
#
# The ring buffers can be visualized as follows:
#
# rootmod = 10
# buflen = 10
# |--------------|--------------|
# 0 10 20
# timestamps beacon roots
#
# To get the corresponding beacon root for a specific timestamp, simply add
# rootmod to the timestamp's index in the first ring buffer. The sum will be
# buflen to the timestamp's index in the first ring buffer. The sum will be
# the storage slot in the second ring buffer where it is stored.


# -----------------------------------------------------------------------------
# MACROS ----------------------------------------------------------------------
# -----------------------------------------------------------------------------

# rootmod returns the HISTORICAL_ROOTS_MODULUS as defined in the EIP.
%def rootmod()
# buflen returns the HISTORY_BUFFER_LENGTH as defined in the EIP.
%def buflen()
98304
%end

Expand Down Expand Up @@ -58,7 +58,7 @@ start:
# Protect the submit routine by verifying the caller is equal to
# sysaddr().
caller # [caller]
push20 sysaddr() # [sysaddr, caller]
push20 sysaddr() # [sysaddr, caller]
eq # [sysaddr == caller]
push1 submit # [submit_lbl, sysaddr == caller]
jumpi # []
Expand All @@ -80,8 +80,8 @@ start:
loadtime:
# Compute the timestamp index and load from storage.
jumpdest # []
push3 rootmod() # [rootmod]
%get_input() # [time, rootmod]
push3 buflen() # [buflen]
%get_input() # [time, buflen]
mod # [time_index]
dup1 # [time_index, time_index]
sload # [timestamp, time_index]
Expand All @@ -99,14 +99,14 @@ loadtime:
loadroot:
# Extend index to get root index.
jumpdest
push3 rootmod() # [rootmod, time_index]
push3 buflen() # [buflen, time_index]
add # [root_index]
sload # [root]

# Write the retrieved root to memory so it can be returned.
push0 # [0, root]
mstore # []

# Return the root.
push1 32 # [size]
push0 # [offset, size]
Expand All @@ -116,10 +116,10 @@ submit:
jumpdest # []

# Calculate the index the timestamp should be stored at, e.g.
# time_index = (time % rootmod).
push3 rootmod() # [rootmod]
timestamp # [time, rootmod]
mod # [time % rootmod]
# time_index = (time % buflen).
push3 buflen() # [buflen]
timestamp # [time, buflen]
mod # [time % buflen]

# Write timestamp into storage slot at time_index.
timestamp # [time, time_index]
Expand All @@ -133,7 +133,7 @@ submit:
push0 # [0, time_index]
calldataload # [root, time_index]
swap1 # [time_index, root]
push3 rootmod() # [rootmod, time_index, root]
push3 buflen() # [buflen, time_index, root]
add # [root_index, root]
sstore # []

Expand Down
14 changes: 7 additions & 7 deletions test/Contract.t.sol.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import "../src/Contract.sol";

address constant addr = 0x000000000000000000000000000000000000000b;
address constant sysaddr = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE;
uint256 constant rootmod = 98304;
uint256 constant buflen = 98304;
bytes32 constant root = hex"88e96d4537bea4d9c05d12549907b32561d3bf31f45aae734cdc119f13406cb6";

function timestamp() view returns (bytes32) {
return bytes32(uint256(block.timestamp));
}

function timestamp_idx() view returns (bytes32) {
return bytes32(uint256(block.timestamp % rootmod));
return bytes32(uint256(block.timestamp % buflen));
}

function root_idx() view returns (bytes32) {
return bytes32(uint256(block.timestamp % rootmod + rootmod));
return bytes32(uint256(block.timestamp % buflen + buflen));
}

contract ContractTest is Test {
Expand Down Expand Up @@ -73,13 +73,13 @@ contract ContractTest is Test {
vm.store(unit, timestamp_idx(), bytes32(time));
vm.store(unit, root_idx(), root);

// Wrap around rootmod once forward.
(bool ret, bytes memory data) = unit.call(bytes.concat(bytes32(time+rootmod)));
// Wrap around buflen once forward.
(bool ret, bytes memory data) = unit.call(bytes.concat(bytes32(time+buflen)));
assertFalse(ret);
assertEq(data, hex"");

// Wrap around rootmod once backward.
(ret, data) = unit.call(bytes.concat(bytes32(time-rootmod)));
// Wrap around buflen once backward.
(ret, data) = unit.call(bytes.concat(bytes32(time-buflen)));
assertFalse(ret);
assertEq(data, hex"");

Expand Down