Skip to content

Commit

Permalink
Use single value for bridged GYD
Browse files Browse the repository at this point in the history
  • Loading branch information
danhper committed Sep 16, 2024
1 parent 4b950bc commit a3aa3ba
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 13 deletions.
25 changes: 20 additions & 5 deletions src/GydL1CCIPEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.17;

import {Initializable} from "upgradeable/proxy/utils/Initializable.sol";
import {StorageSlot} from "oz/utils/StorageSlot.sol";
import {UUPSUpgradeable} from "upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {AccessControlDefaultAdminRulesUpgradeable} from
"upgradeable/access/extensions/AccessControlDefaultAdminRulesUpgradeable.sol";
Expand Down Expand Up @@ -30,6 +31,12 @@ contract GydL1CCIPEscrow is
using Address for address;
using Address for address payable;

// Previously stored in a mapping(uint64 => uint256) at slot 4 where the
// uint64 is the CCIP chain selector
// only Arbitrum was used, so we compute its slot
bytes32 private constant _PREVIOUS_TOTAL_BRIDGED_SLOT =
keccak256(abi.encode(4_949_039_107_694_359_620, 4));

/// @notice GYD contract
IERC20 public gyd;

Expand All @@ -42,7 +49,7 @@ contract GydL1CCIPEscrow is
mapping(uint64 => ChainMetadata) public chainsMetadata;

/// @notice The total amount of GYD bridged per chain
mapping(uint64 => uint256) public totalBridgedGYD;
uint256 public totalBridgedGYD;

/// @notice Disable initializer on deploy
constructor() {
Expand Down Expand Up @@ -77,6 +84,14 @@ contract GydL1CCIPEscrow is
}
}

function initializeTotalBridgedGYD() external {
if (totalBridgedGYD > 0) {
revert InvalidInitialization();
}
totalBridgedGYD =
StorageSlot.getUint256Slot(_PREVIOUS_TOTAL_BRIDGED_SLOT).value;
}

/**
* @dev The GydL1Escrow can only be upgraded by the owner
* @param v new GydL1Escrow implementation
Expand Down Expand Up @@ -150,9 +165,9 @@ contract GydL1CCIPEscrow is
router, destinationChainSelector, evm2AnyMessage, fees
);

uint256 bridged = totalBridgedGYD[destinationChainSelector];
uint256 bridged = totalBridgedGYD;
bridged += amount;
totalBridgedGYD[destinationChainSelector] = bridged;
totalBridgedGYD = bridged;
emit GYDBridged(destinationChainSelector, msg.sender, amount, bridged);
}

Expand Down Expand Up @@ -210,9 +225,9 @@ contract GydL1CCIPEscrow is

(address recipient, uint256 amount, bytes memory data) =
abi.decode(any2EvmMessage.data, (address, uint256, bytes));
uint256 bridged = totalBridgedGYD[any2EvmMessage.sourceChainSelector];
uint256 bridged = totalBridgedGYD;
bridged -= amount;
totalBridgedGYD[any2EvmMessage.sourceChainSelector] = bridged;
totalBridgedGYD = bridged;

gyd.safeTransfer(recipient, amount);
if (data.length > 0) {
Expand Down
14 changes: 6 additions & 8 deletions test/GydL1Escrow.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ contract GydL1EscrowV2Mock is GydL1CCIPEscrow {
virtual
override
{
totalBridgedGYD[0] = 2 * amount;
totalBridgedGYD = 2 * amount;
}
}

Expand Down Expand Up @@ -110,14 +110,14 @@ contract GydL1EscrowTest is Test {
/// @notice Upgrade as admin; make sure it works as expected
function testUpgradeAsAdmin() public {
// Pre-upgrade check
assertEq(proxyV1.totalBridgedGYD(0), 0);
assertEq(proxyV1.totalBridgedGYD(), 0);
vm.expectRevert("ERC20: insufficient allowance");
proxyV1.bridgeToken(0, alice, 1 ether);

vm.startPrank(admin);
proxyV1.upgradeToAndCall(address(v2), "");
proxyV2.bridgeToken(0, alice, 1 ether);
assertEq(proxyV1.totalBridgedGYD(0), 2 ether);
assertEq(proxyV1.totalBridgedGYD(), 2 ether);
}

/// @notice Upgrade as non-admin; make sure it reverted
Expand Down Expand Up @@ -154,9 +154,7 @@ contract GydL1EscrowTest is Test {

assertEq(IERC20(gyd).balanceOf(alice), 0);
assertEq(IERC20(gyd).balanceOf(address(mockedProxyV1)), bridgeAmount);
assertEq(
mockedProxyV1.totalBridgedGYD(arbitrumChainSelector), bridgeAmount
);
assertEq(mockedProxyV1.totalBridgedGYD(), bridgeAmount);

assertEq(router.destinationChainSelector(), arbitrumChainSelector);
assertEq(router.destAddress(), gyd);
Expand All @@ -181,7 +179,7 @@ contract GydL1EscrowTest is Test {
);
vm.stopPrank();

assertEq(proxyV1.totalBridgedGYD(arbitrumChainSelector), bridgeAmount);
assertEq(proxyV1.totalBridgedGYD(), bridgeAmount);
assertEq(IERC20(gyd).balanceOf(alice), 0);
assertEq(IERC20(gyd).balanceOf(address(proxyV1)), bridgeAmount);
}
Expand Down Expand Up @@ -269,7 +267,7 @@ contract GydL1EscrowTest is Test {
vm.stopPrank();

assertEq(IERC20(gyd).balanceOf(bob), bridgeAmount);
assertEq(proxyV1.totalBridgedGYD(arbitrumChainSelector), 0);
assertEq(proxyV1.totalBridgedGYD(), 0);
}

function testUpdateGasLimit() public {
Expand Down
28 changes: 28 additions & 0 deletions test/GydL1EscrowUpgrade.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {Test} from "forge-std/Test.sol";

import {GydL1CCIPEscrow} from "../src/GydL1CCIPEscrow.sol";

contract GydL1EscrowUpgradeTest is Test {
GydL1CCIPEscrow escrow =
GydL1CCIPEscrow(0xa1886c8d748DeB3774225593a70c79454B1DA8a6);

function setUp() public {
vm.createSelectFork(vm.envString("ETH_RPC_URL"), 20_743_048);
}

function testUpgrade() external {
address newImpl = address(new GydL1CCIPEscrow());
bytes memory data = abi.encodeWithSelector(
GydL1CCIPEscrow.initializeTotalBridgedGYD.selector