Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: addWhitelistTokens require more token info than just token address #39

Merged
merged 19 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
1 change: 0 additions & 1 deletion script/13_DepositValidator.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ contract DepositScript is BaseScript {

uint256 internal constant GENESIS_BLOCK_TIMESTAMP = 1_695_902_400;
uint256 internal constant SECONDS_PER_SLOT = 12;
address constant VIRTUAL_STAKED_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint256 constant GWEI_TO_WEI = 1e9;

function setUp() public virtual override {
Expand Down
43 changes: 32 additions & 11 deletions script/3_Setup.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ contract SetupScript is BaseScript {
vm.stopBroadcast();

// 2. setup Exocore contracts to make them ready for sending and receiving messages from client chain
// gateway
// gateway, and register client chain meta data as well as well as adding tokens to whtielist to enable
// restaking
vm.selectFork(exocore);
// Exocore validator set should be the owner of these contracts and only owner could setup contracts state
vm.startBroadcast(exocoreValidatorSet.privateKey);
Expand All @@ -75,16 +76,36 @@ contract SetupScript is BaseScript {
address(clientGateway), address(clientChainLzEndpoint)
);
}
// this would also register clientChainId to Exocore native module
exocoreGateway.setPeer(clientChainId, address(clientGateway).toBytes32());
vm.stopBroadcast();

// 3. we should register whitelist tokens to exocore
vm.selectFork(clientChain);
// Exocore validator set should be the owner of these contracts and only owner could add whitelist tokens
vm.startBroadcast(exocoreValidatorSet.privateKey);
whitelistTokens.push(address(restakeToken));
clientGateway.addWhitelistTokens(whitelistTokens);
// first register clientChainId to Exocore native module and set peer for client chain gateway to be ready for
// messaging
exocoreGateway.registerOrUpdateClientChain(
clientChainId, address(clientGateway).toBytes32(), 20, "clientChain", "", "secp256k1"
);
// second add whitelist tokens and their meta data on Exocore side to enable LST Restaking and Native Restaking,
// and this would also add token addresses to client chain gateway's whitelist
bytes32[] memory whitelistTokensBytes32 = new bytes32[](2);
uint8[] memory decimals = new uint8[](2);
uint256[] memory tvlLimits = new uint256[](2);
string[] memory names = new string[](2);
string[] memory metaData = new string[](2);

whitelistTokensBytes32[0] = bytes32(bytes20(address(restakeToken)));
decimals[0] = restakeToken.decimals();
tvlLimits[0] = 1e10 ether;
names[0] = "RestakeToken";
metaData[0] = "";

whitelistTokensBytes32[1] = bytes32(bytes20(VIRTUAL_STAKED_ETH_ADDRESS));
decimals[1] = 18;
tvlLimits[1] = 1e8 ether;
names[1] = "RestakeToken";
metaData[1] = "";

uint256 messageLength = TOKEN_ADDRESS_BYTES_LENGTH * whitelistTokensBytes32.length + 2;
uint256 nativeFee = exocoreGateway.quote(clientChainId, new bytes(messageLength));
exocoreGateway.addWhitelistTokens{value: nativeFee}(
clientChainId, whitelistTokensBytes32, decimals, tvlLimits, names, metaData
);
vm.stopBroadcast();
}

Expand Down
2 changes: 2 additions & 0 deletions script/BaseScript.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ contract BaseScript is Script {

uint256 constant DEPOSIT_AMOUNT = 1 ether;
uint256 constant WITHDRAW_AMOUNT = 1 ether;
address internal constant VIRTUAL_STAKED_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint256 internal constant TOKEN_ADDRESS_BYTES_LENGTH = 32;

bool useExocorePrecompileMock;
bool useEndpointMock;
Expand Down
2 changes: 1 addition & 1 deletion src/core/Bootstrap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ contract Bootstrap is
}

// implementation of ITokenWhitelister
function addWhitelistTokens(address[] calldata tokens) external payable beforeLocked onlyOwner whenNotPaused {
function addWhitelistTokens(address[] calldata tokens) external beforeLocked onlyOwner whenNotPaused {
_addWhitelistTokens(tokens);
}

Expand Down
25 changes: 5 additions & 20 deletions src/core/ClientChainGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ contract ClientChainGateway is
this.afterReceiveWithdrawRewardResponse.selector;
_registeredResponseHooks[Action.REQUEST_DEPOSIT_THEN_DELEGATE_TO] =
this.afterReceiveDepositThenDelegateToResponse.selector;
_registeredResponseHooks[Action.REQUEST_REGISTER_TOKENS] = this.afterReceiveRegisterTokensResponse.selector;

_whiteListFunctionSelectors[Action.REQUEST_ADD_WHITELIST_TOKENS] =
this.afterReceiveAddWhitelistTokensRequest.selector;

bootstrapped = true;

Expand Down Expand Up @@ -119,25 +121,8 @@ contract ClientChainGateway is
_unpause();
}

// implementation of ITokenWhitelister
function addWhitelistTokens(address[] calldata tokens) external payable onlyOwner whenNotPaused nonReentrant {
_addWhitelistTokens(tokens);
}

function _addWhitelistTokens(address[] calldata tokens) internal {
require(tokens.length <= type(uint8).max, "ClientChainGateway: tokens length should not execeed 255");

bytes memory actionArgs = abi.encodePacked(uint8(tokens.length));
for (uint256 i; i < tokens.length; i++) {
address token = tokens[i];
require(token != address(0), "ClientChainGateway: zero token address");
require(!isWhitelistedToken[token], "ClientChainGateway: token should not be whitelisted before");

actionArgs = abi.encodePacked(actionArgs, bytes32(bytes20(token)));
}

bytes memory encodedRequest = abi.encode(tokens);
_processRequest(Action.REQUEST_REGISTER_TOKENS, actionArgs, encodedRequest);
function addWhitelistTokens(address[] calldata) external onlyOwner whenNotPaused {
revert("this function is not supported for client chain, please register on Exocore");
}

// implementation of ITokenWhitelister
Expand Down
23 changes: 14 additions & 9 deletions src/core/ClientGatewayLzReceiver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ abstract contract ClientGatewayLzReceiver is PausableUpgradeable, OAppReceiverUp
error UnsupportedResponse(Action act);
error UnexpectedResponse(uint64 nonce);
error DepositShouldNotFailOnExocore(address token, address depositor);
error InvalidAddWhitelistTokensRequest(uint256 expectedLength, uint256 actualLength);

modifier onlyCalledFromThis() {
require(
Expand Down Expand Up @@ -182,30 +183,34 @@ abstract contract ClientGatewayLzReceiver is PausableUpgradeable, OAppReceiverUp
emit DepositThenDelegateResult(delegateSuccess, delegator, operator, token, amount);
}

function afterReceiveRegisterTokensResponse(bytes calldata requestPayload, bytes calldata responsePayload)
function afterReceiveAddWhitelistTokensRequest(bytes calldata requestPayload)
public
onlyCalledFromThis
whenNotPaused
{
address[] memory tokens = abi.decode(requestPayload, (address[]));
uint8 count = uint8(requestPayload[0]);
uint256 expectedLength = count * TOKEN_ADDRESS_BYTES_LENGTH + 1;
if (requestPayload.length != expectedLength) {
revert InvalidAddWhitelistTokensRequest(expectedLength, requestPayload.length);
}

bool success = (uint8(bytes1(responsePayload[0])) == 1);
if (success) {
for (uint256 i; i < tokens.length; i++) {
address token = tokens[i];
for (uint256 i; i < count; i++) {
uint256 start = i * TOKEN_ADDRESS_BYTES_LENGTH + 1;
uint256 end = start + TOKEN_ADDRESS_BYTES_LENGTH;
address token = address(bytes20(requestPayload[start:end]));

if (!isWhitelistedToken[token]) {
isWhitelistedToken[token] = true;
whitelistTokens.push(token);

// deploy the corresponding vault if not deployed before
if (address(tokenToVault[token]) == address(0)) {
if (token != VIRTUAL_STAKED_ETH_ADDRESS && address(tokenToVault[token]) == address(0)) {
_deployVault(token);
}

emit WhitelistTokenAdded(token);
}
}

emit RegisterTokensResult(success);
}

}
Loading
Loading