-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: upgrade contract while changing vars
- Loading branch information
Uriel Mihura
committed
Jan 19, 2024
1 parent
95d196d
commit 8e04ca6
Showing
6 changed files
with
621 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.21; | ||
|
||
import "forge-std/Test.sol"; | ||
import "../src/YABTransfer.sol"; | ||
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | ||
import {YABTransfer_lessVars} from "./mock_contracts/YABTransfer_lessVars.sol"; | ||
import {YABTransfer_reorgVars} from "./mock_contracts/YABTransfer_reorgVars.sol"; | ||
import {YABTransfer_moreVars_before} from "./mock_contracts/YABTransfer_moreVars_before.sol"; | ||
import {YABTransfer_moreVars_after} from "./mock_contracts/YABTransfer_moreVars_after.sol"; | ||
|
||
|
||
contract TransferTest is Test { | ||
address public deployer = address(0xB321099cf86D9BB913b891441B014c03a6CcFc54); | ||
address public marketMaker; | ||
|
||
YABTransfer public yab; | ||
ERC1967Proxy public proxy; | ||
YABTransfer public yab_caller; | ||
|
||
function setUp() public { | ||
vm.startPrank(deployer); | ||
|
||
address snMessagingAddress = 0xde29d060D45901Fb19ED6C6e959EB22d8626708e; | ||
uint256 snEscrowAddress = 0x0; | ||
uint256 snEscrowWithdrawSelector = 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77; | ||
marketMaker = 0xda963fA72caC2A3aC01c642062fba3C099993D56; | ||
|
||
yab = new YABTransfer(); | ||
proxy = new ERC1967Proxy(address(yab), ""); | ||
yab_caller = YABTransfer(address(proxy)); | ||
yab_caller.initialize(snMessagingAddress, snEscrowAddress, snEscrowWithdrawSelector, marketMaker); | ||
|
||
vm.stopPrank(); | ||
} | ||
|
||
function deploy_and_upgrade_lessVars() public returns (YABTransfer_lessVars){ | ||
YABTransfer_lessVars yab_lessVars = new YABTransfer_lessVars(); | ||
YABTransfer_lessVars yab_lessVars_caller = YABTransfer_lessVars(address(proxy)); | ||
yab_lessVars_caller.upgradeToAndCall(address(yab_lessVars), ''); | ||
return yab_lessVars_caller; | ||
} | ||
|
||
function deploy_and_upgrade_reorgVars() public returns (YABTransfer_reorgVars){ | ||
YABTransfer_reorgVars yab_reorgVars = new YABTransfer_reorgVars(); | ||
YABTransfer_reorgVars yab_reorgVars_caller = YABTransfer_reorgVars(address(proxy)); | ||
yab_reorgVars_caller.upgradeToAndCall(address(yab_reorgVars), ''); | ||
return yab_reorgVars_caller; | ||
} | ||
|
||
function deploy_and_upgrade_oldVars() public returns (YABTransfer){ | ||
YABTransfer yab_old = new YABTransfer(); | ||
YABTransfer yab_old_caller = YABTransfer(address(proxy)); | ||
yab_old_caller.upgradeToAndCall(address(yab_old), ''); | ||
return yab_old_caller; | ||
} | ||
|
||
function deploy_and_upgrade_moreVars_before() public returns (YABTransfer_moreVars_before){ | ||
YABTransfer_moreVars_before yab_moreVars_before = new YABTransfer_moreVars_before(); | ||
YABTransfer_moreVars_before yab_moreVars_before_caller = YABTransfer_moreVars_before(address(proxy)); | ||
yab_moreVars_before_caller.upgradeToAndCall(address(yab_moreVars_before), ''); | ||
return yab_moreVars_before_caller; | ||
} | ||
|
||
function deploy_and_upgrade_moreVars_after() public returns (YABTransfer_moreVars_after){ | ||
YABTransfer_moreVars_after yab_moreVars_after = new YABTransfer_moreVars_after(); | ||
YABTransfer_moreVars_after yab_moreVars_after_caller = YABTransfer_moreVars_after(address(proxy)); | ||
yab_moreVars_after_caller.upgradeToAndCall(address(yab_moreVars_after), ''); | ||
return yab_moreVars_after_caller; | ||
} | ||
|
||
|
||
// function test_read_values() public { //ok | ||
// assertEq(yab_caller.getEscrowWithdrawSelector(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// assertEq(yab_caller.getEscrowAddress(), 0x0); | ||
// } | ||
|
||
// function test_should_fail_read_deleted_values() public { //ok? | ||
// vm.startPrank(deployer); | ||
// YABTransfer_lessVars yab_lessVars_caller = deploy_and_upgrade_lessVars(); | ||
// vm.expectRevert(); //function does not exist | ||
// yab_caller.getEscrowWithdrawSelector(); | ||
// vm.expectRevert(); //function does not exist | ||
// yab_caller.getEscrowAddress(); | ||
// vm.stopPrank(); | ||
// } | ||
|
||
// //WARNING | ||
// function test_read_reorg_values() public { //this test proves reorganizing values in storage IS HIGHLY DANGEROUS | ||
// vm.startPrank(deployer); | ||
// assertEq(yab_caller.getEscrowWithdrawSelector(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// assertEq(yab_caller.getEscrowAddress(), 0x0); | ||
|
||
// YABTransfer_reorgVars yab_reorgVars_caller = deploy_and_upgrade_reorgVars(); | ||
|
||
// assertEq(yab_reorgVars_caller.getEscrowWithdrawSelector(), 0x0); | ||
// assertEq(yab_reorgVars_caller.getEscrowAddress(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// vm.stopPrank(); | ||
// } | ||
|
||
// //WARNING | ||
// function test_read_delAndReorg_values() public {//this test proves reorganizing values in storage IS HIGHLY DANGEROUS | ||
// vm.startPrank(deployer); | ||
// assertEq(yab_caller.getEscrowWithdrawSelector(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// assertEq(yab_caller.getEscrowAddress(), 0x0); | ||
|
||
// YABTransfer_lessVars yab_lessVars_caller = deploy_and_upgrade_lessVars(); | ||
// YABTransfer_reorgVars yab_reorgVars_caller = deploy_and_upgrade_reorgVars(); | ||
|
||
// assertEq(yab_reorgVars_caller.getEscrowWithdrawSelector(), 0x0); | ||
// assertEq(yab_reorgVars_caller.getEscrowAddress(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// vm.stopPrank(); | ||
// } | ||
|
||
// function test_read_var_before() public { //WIP | ||
// vm.startPrank(deployer); | ||
// vm.expectRevert(); //function does not exist | ||
// yab_caller.getNewVarBefore(); | ||
|
||
// YABTransfer_moreVars_before yab_moreVars_before_caller = (); | ||
|
||
// assertEq(yab_moreVars_before_caller.getEscrowWithdrawSelector(), 0x0); | ||
// assertEq(yab_moreVars_before_caller.getEscrowAddress(), 0x15511cc3694f64379908437d6d64458dc76d02482052bfb8a5b33a72c054c77); | ||
// vm.stopPrank(); | ||
// } | ||
} |
119 changes: 119 additions & 0 deletions
119
contracts/solidity/test/mock_contracts/YABTransfer_lessVars.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.21; | ||
|
||
import {IStarknetMessaging} from "starknet/IStarknetMessaging.sol"; | ||
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
|
||
|
||
// This contract is the same as YABTransfer.sol but it does not have: | ||
// _snEscrowAddress and _snEscrowWithdrawSelector storage, and their related functions | ||
contract YABTransfer_lessVars is Initializable, OwnableUpgradeable, UUPSUpgradeable { | ||
struct TransferInfo { | ||
uint256 destAddress; | ||
uint256 amount; | ||
bool isUsed; | ||
} | ||
|
||
event Transfer(uint256 indexed orderId, address srcAddress, TransferInfo transferInfo); | ||
|
||
mapping(bytes32 => TransferInfo) public transfers; | ||
address private _marketMaker; | ||
|
||
IStarknetMessaging private _snMessaging; | ||
// uint256 private _snEscrowAddress; | ||
// uint256 private _snEscrowWithdrawSelector; | ||
|
||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
// no constructors can be used in upgradeable contracts. | ||
function initialize( | ||
address snMessaging, | ||
// uint256 snEscrowAddress, | ||
// uint256 snEscrowWithdrawSelector, | ||
address marketMaker) public initializer { | ||
__Ownable_init(msg.sender); | ||
__UUPSUpgradeable_init(); | ||
|
||
_snMessaging = IStarknetMessaging(snMessaging); | ||
// _snEscrowAddress = snEscrowAddress; | ||
// _snEscrowWithdrawSelector = snEscrowWithdrawSelector; | ||
_marketMaker = marketMaker; | ||
} | ||
|
||
|
||
function transfer(uint256 orderId, uint256 destAddress, uint256 amount) external payable onlyOwnerOrMM { | ||
require(destAddress != 0, "Invalid destination address."); | ||
require(amount > 0, "Invalid amount, should be higher than 0."); | ||
require(msg.value == amount, "Invalid amount, should match msg.value."); | ||
|
||
bytes32 index = keccak256(abi.encodePacked(orderId, destAddress, amount)); | ||
require(transfers[index].isUsed == false, "Transfer already processed."); | ||
|
||
transfers[index] = TransferInfo({destAddress: destAddress, amount: amount, isUsed: true}); | ||
|
||
(bool success,) = payable(address(uint160(destAddress))).call{value: msg.value}(""); | ||
|
||
require(success, "Transfer failed."); | ||
emit Transfer(orderId, msg.sender, transfers[index]); | ||
} | ||
|
||
function withdraw(uint256 orderId, uint256 destAddress, uint256 amount) external payable onlyOwnerOrMM { | ||
bytes32 index = keccak256(abi.encodePacked(orderId, destAddress, amount)); | ||
TransferInfo storage transferInfo = transfers[index]; | ||
require(transferInfo.isUsed == true, "Transfer not found."); | ||
|
||
uint256[] memory payload = new uint256[](5); | ||
payload[0] = orderId; | ||
payload[1] = 0; | ||
payload[2] = transferInfo.destAddress; | ||
payload[3] = transferInfo.amount; | ||
payload[4] = 0; | ||
|
||
// _snMessaging.sendMessageToL2{value: msg.value}( | ||
// _snEscrowAddress, | ||
// _snEscrowWithdrawSelector, | ||
// payload); | ||
} | ||
|
||
// function setEscrowAddress(uint256 snEscrowAddress) external onlyOwner { | ||
// _snEscrowAddress = snEscrowAddress; | ||
// } | ||
|
||
// function setEscrowWithdrawSelector(uint256 snEscrowWithdrawSelector) external onlyOwner { | ||
// _snEscrowWithdrawSelector = snEscrowWithdrawSelector; | ||
// } | ||
|
||
// function getEscrowAddress() external view returns (uint256) { | ||
// return _snEscrowAddress; | ||
// } | ||
|
||
// function getEscrowWithdrawSelector() external view returns (uint256) { | ||
// return _snEscrowWithdrawSelector; | ||
// } | ||
|
||
|
||
//// MM ACL: | ||
|
||
function getMMAddress() external view onlyOwnerOrMM returns (address) { | ||
return _marketMaker; | ||
} | ||
|
||
function setMMAddress(address newMMAddress) external onlyOwner { | ||
_marketMaker = newMMAddress; | ||
} | ||
|
||
function getOwner() external view returns (address) { | ||
return owner(); | ||
} | ||
|
||
modifier onlyOwnerOrMM { | ||
require(msg.sender == owner() || msg.sender == _marketMaker, "Only Owner or MM can call this function"); | ||
_; | ||
} | ||
|
||
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} | ||
} |
125 changes: 125 additions & 0 deletions
125
contracts/solidity/test/mock_contracts/YABTransfer_moreVars_after.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.21; | ||
|
||
import {IStarknetMessaging} from "starknet/IStarknetMessaging.sol"; | ||
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
|
||
contract YABTransfer_moreVars_after is Initializable, OwnableUpgradeable, UUPSUpgradeable { | ||
struct TransferInfo { | ||
uint256 destAddress; | ||
uint256 amount; | ||
bool isUsed; | ||
} | ||
|
||
event Transfer(uint256 indexed orderId, address srcAddress, TransferInfo transferInfo); | ||
|
||
mapping(bytes32 => TransferInfo) public transfers; | ||
address private _marketMaker; | ||
|
||
IStarknetMessaging private _snMessaging; | ||
uint256 private _snEscrowAddress; | ||
uint256 private _snEscrowWithdrawSelector; | ||
uint256 private _newVarAfter; | ||
|
||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
// no constructors can be used in upgradeable contracts. | ||
function initialize( | ||
address snMessaging, | ||
uint256 snEscrowAddress, | ||
uint256 snEscrowWithdrawSelector, | ||
address marketMaker) public initializer { | ||
__Ownable_init(msg.sender); | ||
__UUPSUpgradeable_init(); | ||
|
||
_snMessaging = IStarknetMessaging(snMessaging); | ||
_snEscrowAddress = snEscrowAddress; | ||
_snEscrowWithdrawSelector = snEscrowWithdrawSelector; | ||
_marketMaker = marketMaker; | ||
} | ||
|
||
|
||
function transfer(uint256 orderId, uint256 destAddress, uint256 amount) external payable onlyOwnerOrMM { | ||
require(destAddress != 0, "Invalid destination address."); | ||
require(amount > 0, "Invalid amount, should be higher than 0."); | ||
require(msg.value == amount, "Invalid amount, should match msg.value."); | ||
|
||
bytes32 index = keccak256(abi.encodePacked(orderId, destAddress, amount)); | ||
require(transfers[index].isUsed == false, "Transfer already processed."); | ||
|
||
transfers[index] = TransferInfo({destAddress: destAddress, amount: amount, isUsed: true}); | ||
|
||
(bool success,) = payable(address(uint160(destAddress))).call{value: msg.value}(""); | ||
|
||
require(success, "Transfer failed."); | ||
emit Transfer(orderId, msg.sender, transfers[index]); | ||
} | ||
|
||
function withdraw(uint256 orderId, uint256 destAddress, uint256 amount) external payable onlyOwnerOrMM { | ||
bytes32 index = keccak256(abi.encodePacked(orderId, destAddress, amount)); | ||
TransferInfo storage transferInfo = transfers[index]; | ||
require(transferInfo.isUsed == true, "Transfer not found."); | ||
|
||
uint256[] memory payload = new uint256[](5); | ||
payload[0] = orderId; | ||
payload[1] = 0; | ||
payload[2] = transferInfo.destAddress; | ||
payload[3] = transferInfo.amount; | ||
payload[4] = 0; | ||
|
||
_snMessaging.sendMessageToL2{value: msg.value}( | ||
_snEscrowAddress, | ||
_snEscrowWithdrawSelector, | ||
payload); | ||
} | ||
|
||
function setEscrowAddress(uint256 snEscrowAddress) external onlyOwner { | ||
_snEscrowAddress = snEscrowAddress; | ||
} | ||
|
||
function setEscrowWithdrawSelector(uint256 snEscrowWithdrawSelector) external onlyOwner { | ||
_snEscrowWithdrawSelector = snEscrowWithdrawSelector; | ||
} | ||
|
||
function getEscrowAddress() external view returns (uint256) { | ||
return _snEscrowAddress; | ||
} | ||
|
||
function getEscrowWithdrawSelector() external view returns (uint256) { | ||
return _snEscrowWithdrawSelector; | ||
} | ||
|
||
function getNewVarAfter() external view returns (uint256) { | ||
return _newVarAfter; | ||
} | ||
|
||
function setNewVarAfter(uint256 newValue) external { | ||
_newVarAfter = newValue; | ||
} | ||
|
||
|
||
//// MM ACL: | ||
|
||
function getMMAddress() external view onlyOwnerOrMM returns (address) { | ||
return _marketMaker; | ||
} | ||
|
||
function setMMAddress(address newMMAddress) external onlyOwner { | ||
_marketMaker = newMMAddress; | ||
} | ||
|
||
function getOwner() external view returns (address) { | ||
return owner(); | ||
} | ||
|
||
modifier onlyOwnerOrMM { | ||
require(msg.sender == owner() || msg.sender == _marketMaker, "Only Owner or MM can call this function"); | ||
_; | ||
} | ||
|
||
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} | ||
} |
Oops, something went wrong.