-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #210 from etherfi-protocol/syko/feature/admin_can_…
…unpause_liquifier Upgrade Liquifier so that Admin can {unPause, update the deposit cap} + Deterministic Deploy via create2
- Loading branch information
Showing
9 changed files
with
278 additions
and
224 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,13 @@ | ||
{ "version": "1.0", "chainId": "1", "meta": { "name": "Transactions Batch", "description": "", "txBuilderVersion": "1.16.5", "createdFromSafeAddress": "0xcdd57D11476c22d265722F68390b036f3DA48c21" }, "transactions": [ | ||
{ | ||
"to": "0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761", | ||
"value": "0", | ||
"data": "0x01d5062a0000000000000000000000009ffdf407cde9a93c47611799da23924af3ef764f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003f48000000000000000000000000000000000000000000000000000000000000000243659cfe6000000000000000000000000a1a15fb15cbda9e6c480c5bca6e9aba9c5e2ff9500000000000000000000000000000000000000000000000000000000" | ||
} | ||
, | ||
{ | ||
"to": "0x9f26d4C958fD811A1F59B01B86Be7dFFc9d20761", | ||
"value": "0", | ||
"data": "0x134008d30000000000000000000000009ffdf407cde9a93c47611799da23924af3ef764f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000243659cfe6000000000000000000000000a1a15fb15cbda9e6c480c5bca6e9aba9c5e2ff9500000000000000000000000000000000000000000000000000000000" | ||
} | ||
] } |
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,194 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.13; | ||
|
||
import {console} from "forge-std/console.sol"; | ||
import {console2} from "forge-std/console2.sol"; | ||
|
||
|
||
contract ContractCodeChecker { | ||
|
||
event ByteMismatchSegment( | ||
uint256 startIndex, | ||
uint256 endIndex, | ||
bytes aSegment, | ||
bytes bSegment | ||
); | ||
|
||
function compareBytes(bytes memory a, bytes memory b) internal returns (bool) { | ||
if (a.length != b.length) { | ||
// Length mismatch, emit one big segment for the difference if that’s desirable | ||
// or just return false. For clarity, we can just return false here. | ||
return false; | ||
} | ||
|
||
uint256 len = a.length; | ||
uint256 start = 0; | ||
bool inMismatch = false; | ||
bool anyMismatch = false; | ||
|
||
for (uint256 i = 0; i < len; i++) { | ||
bool mismatch = (a[i] != b[i]); | ||
if (mismatch && !inMismatch) { | ||
// Starting a new mismatch segment | ||
start = i; | ||
inMismatch = true; | ||
} else if (!mismatch && inMismatch) { | ||
// Ending the current mismatch segment at i-1 | ||
emitMismatchSegment(a, b, start, i - 1); | ||
inMismatch = false; | ||
anyMismatch = true; | ||
} | ||
} | ||
|
||
// If we ended with a mismatch still open, close it out | ||
if (inMismatch) { | ||
emitMismatchSegment(a, b, start, len - 1); | ||
anyMismatch = true; | ||
} | ||
|
||
// If no mismatch segments were found, everything matched | ||
return !anyMismatch; | ||
} | ||
|
||
function emitMismatchSegment( | ||
bytes memory a, | ||
bytes memory b, | ||
uint256 start, | ||
uint256 end | ||
) internal { | ||
// endIndex is inclusive | ||
uint256 segmentLength = end - start + 1; | ||
|
||
bytes memory aSegment = new bytes(segmentLength); | ||
bytes memory bSegment = new bytes(segmentLength); | ||
|
||
for (uint256 i = 0; i < segmentLength; i++) { | ||
aSegment[i] = a[start + i]; | ||
bSegment[i] = b[start + i]; | ||
} | ||
|
||
string memory aHex = bytesToHexString(aSegment); | ||
string memory bHex = bytesToHexString(bSegment); | ||
|
||
console2.log("- Mismatch segment at index [%s, %s]", start, end); | ||
console2.logString(string.concat(" - ", aHex)); | ||
console2.logString(string.concat(" - ", bHex)); | ||
|
||
emit ByteMismatchSegment(start, end, aSegment, bSegment); | ||
} | ||
|
||
function bytesToHexString(bytes memory data) internal pure returns (string memory) { | ||
bytes memory alphabet = "0123456789abcdef"; | ||
|
||
// Every byte corresponds to two hex characters | ||
bytes memory str = new bytes(2 + data.length * 2); | ||
str[0] = '0'; | ||
str[1] = 'x'; | ||
for (uint256 i = 0; i < data.length; i++) { | ||
str[2 + i * 2] = alphabet[uint8(data[i] >> 4)]; | ||
str[3 + i * 2] = alphabet[uint8(data[i] & 0x0f)]; | ||
} | ||
return string(str); | ||
} | ||
|
||
// Compare the full bytecode of two deployed contracts, ensuring a perfect match. | ||
function verifyFullMatch(address deployedImpl, address localDeployed) public { | ||
console2.log("Verifying full bytecode match..."); | ||
bytes memory localBytecode = address(localDeployed).code; | ||
bytes memory onchainRuntimeBytecode = address(deployedImpl).code; | ||
|
||
if (compareBytes(localBytecode, onchainRuntimeBytecode)) { | ||
console2.log("-> Full Bytecode Match: Success\n"); | ||
} else { | ||
console2.log("-> Full Bytecode Match: Fail\n"); | ||
} | ||
} | ||
|
||
function verifyPartialMatch(address deployedImpl, address localDeployed) public { | ||
console2.log("Verifying partial bytecode match..."); | ||
|
||
// Fetch runtime bytecode from on-chain addresses | ||
bytes memory localBytecode = localDeployed.code; | ||
bytes memory onchainRuntimeBytecode = deployedImpl.code; | ||
|
||
// Optionally check length first (not strictly necessary if doing a partial match) | ||
if (localBytecode.length == 0 || onchainRuntimeBytecode.length == 0) { | ||
revert("One of the bytecode arrays is empty, cannot verify."); | ||
} | ||
|
||
// Attempt to trim metadata from both local and on-chain bytecode | ||
bytes memory trimmedLocal = trimMetadata(localBytecode); | ||
bytes memory trimmedOnchain = trimMetadata(onchainRuntimeBytecode); | ||
|
||
// If trimmed lengths differ significantly, it suggests structural differences in code | ||
if (trimmedLocal.length != trimmedOnchain.length) { | ||
revert("Post-trim length mismatch: potential code differences."); | ||
} | ||
|
||
// Compare trimmed arrays byte-by-byte | ||
if (compareBytes(trimmedLocal, trimmedOnchain)) { | ||
console2.log("-> Partial Bytecode Match: Success\n"); | ||
} else { | ||
console2.log("-> Partial Bytecode Match: Fail\n"); | ||
} | ||
} | ||
|
||
function verifyLengthMatch(address deployedImpl, address localDeployed) public { | ||
console2.log("Verifying length match..."); | ||
bytes memory localBytecode = localDeployed.code; | ||
bytes memory onchainRuntimeBytecode = deployedImpl.code; | ||
|
||
if (localBytecode.length == onchainRuntimeBytecode.length) { | ||
console2.log("-> Length Match: Success\n"); | ||
} else { | ||
console2.log("-> Length Match: Fail\n"); | ||
} | ||
} | ||
|
||
function verifyContractByteCodeMatch(address deployedImpl, address localDeployed) public { | ||
verifyLengthMatch(deployedImpl, localDeployed); | ||
verifyPartialMatch(deployedImpl, localDeployed); | ||
verifyFullMatch(deployedImpl, localDeployed); | ||
} | ||
|
||
// A helper function to remove metadata (CBOR encoded) from the end of the bytecode. | ||
// This is a heuristic based on known patterns in the metadata. | ||
function trimMetadata(bytes memory code) internal pure returns (bytes memory) { | ||
// Metadata usually starts with 0xa2 or a similar tag near the end. | ||
// We can scan backward for a known marker. | ||
// In Solidity 0.8.x, metadata often starts near the end with 0xa2 0x64 ... pattern. | ||
// This is a simplified approach and may need refinement. | ||
|
||
// For a more robust approach, you'd analyze the last bytes. | ||
// Typically, the CBOR metadata is at the very end of the bytecode. | ||
uint256 length = code.length; | ||
if (length < 4) { | ||
// Bytecode too short to have metadata | ||
return code; | ||
} | ||
|
||
// Scan backward for a CBOR header (0xa2). | ||
// We'll just look for 0xa2 from the end and truncate there. | ||
for (uint256 i = length - 1; i > 0; i--) { | ||
if (code[i] == 0xa2) { | ||
console2.log("Found metadata start at index: ", i); | ||
// print 8 bytes from this point | ||
bytes memory tmp = new bytes(8); | ||
for (uint256 j = 0; j < 8; j++) { | ||
tmp[j] = code[i + j]; | ||
} | ||
|
||
// Found a possible metadata start. We'll cut just before 0xa2. | ||
bytes memory trimmed = new bytes(i); | ||
for (uint256 j = 0; j < i; j++) { | ||
trimmed[j] = code[j]; | ||
} | ||
return trimmed; | ||
} | ||
} | ||
|
||
// If no metadata marker found, return as is. | ||
return code; | ||
} | ||
|
||
} |
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,15 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/utils/Create2.sol"; | ||
|
||
contract Create2Factory { | ||
event Deployed(address addr, address deployer, bytes32 bytecode_hash, bytes32 salt); | ||
|
||
function deploy(bytes memory code, bytes32 salt) external payable returns (address) { | ||
address addr = Create2.deploy(msg.value, salt, code); | ||
|
||
emit Deployed(addr, address(this), keccak256(code), salt); | ||
return addr; | ||
} | ||
} |
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,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.24; | ||
|
||
import "forge-std/Script.sol"; | ||
// import "../../src/eBtcRateProvider.sol"; | ||
// import "../../src/helpers/EtherFiViewer.sol"; | ||
import "../../src/EtherFiNodesManager.sol"; | ||
import "../../src/EtherFiNode.sol"; | ||
import "../../src/EtherFiAdmin.sol"; | ||
import "../../src/EtherFiOracle.sol"; | ||
import "../../src/LiquidityPool.sol"; | ||
import "../../src/Liquifier.sol"; | ||
|
||
import "../Create2Factory.sol"; | ||
|
||
|
||
contract Deploy is Script { | ||
bytes32 immutable salt = keccak256("ETHER_FI"); | ||
Create2Factory immutable factory = Create2Factory(0x6521991A0BC180a5df7F42b27F4eE8f3B192BA62); | ||
|
||
function run() external { | ||
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); | ||
vm.selectFork(vm.createFork(vm.envString("MAINNET_RPC_URL"))); | ||
|
||
vm.startBroadcast(deployerPrivateKey); | ||
bytes memory code = abi.encodePacked(type(Liquifier).creationCode); | ||
factory.deploy(code, salt); | ||
} | ||
} |
Oops, something went wrong.