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

Mark assembly blocks as safe #521

Merged
merged 2 commits into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 8 additions & 7 deletions bridge/contracts/Dynamics.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,14 @@ contract Dynamics is Initializable, IDynamics, ImmutableSnapshots {
function _deployStorage(bytes memory data) internal returns (address) {
bytes memory deployCode = abi.encodePacked(_UNIVERSAL_DEPLOY_CODE, data);
address addr;
assembly {
assembly ("memory-safe") {
addr := create(0, add(deployCode, 0x20), mload(deployCode))
if iszero(addr) {
//if contract creation fails, we want to return any err messages
returndatacopy(0x00, 0x00, returndatasize())
//revert and return errors
revert(0x00, returndatasize())
let ptr := mload(0x40)
mstore(0x40, add(ptr, returndatasize()))
returndatacopy(ptr, 0x00, returndatasize())
revert(ptr, returndatasize())
}
}
emit DeployedStorageContract(addr);
Expand Down Expand Up @@ -280,7 +281,7 @@ contract Dynamics is Initializable, IDynamics, ImmutableSnapshots {
uint8[8] memory sizes = [8, 24, 32, 32, 32, 64, 64, 128];
uint256 dynamicValuesTotalSize = 48;
uint256 extCodeSize;
assembly {
assembly ("memory-safe") {
ptr := mload(0x40)
retPtr := values
extCodeSize := extcodesize(addr)
Expand All @@ -292,7 +293,7 @@ contract Dynamics is Initializable, IDynamics, ImmutableSnapshots {

for (uint8 i = 0; i < sizes.length; i++) {
uint8 size = sizes[i];
assembly {
assembly ("memory-safe") {
mstore(retPtr, shr(sub(256, size), mload(ptr)))
ptr := add(ptr, div(size, 8))
retPtr := add(retPtr, 0x20)
Expand Down Expand Up @@ -330,7 +331,7 @@ contract Dynamics is Initializable, IDynamics, ImmutableSnapshots {
uint256 minorVersion,
uint256 patch
) internal pure returns (uint256 fullVersion) {
assembly {
assembly ("memory-safe") {
fullVersion := or(or(shl(64, majorVersion), shl(32, minorVersion)), patch)
}
}
Expand Down
17 changes: 8 additions & 9 deletions bridge/contracts/Foundation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.16;

import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "contracts/utils/auth/ImmutableFactory.sol";
import "contracts/utils/auth/ImmutableAToken.sol";
import "contracts/utils/EthSafeTransfer.sol";
Expand All @@ -19,6 +20,8 @@ contract Foundation is
ImmutableFactory,
ImmutableAToken
{
using Address for address;

constructor() ImmutableFactory(msg.sender) ImmutableAToken() {}

function initialize() public initializer onlyFactory {}
Expand Down Expand Up @@ -52,14 +55,10 @@ contract Foundation is
/// Delegates a call to the specified contract with any set of parameters encoded
/// @param target_ The address of the contract to be delagated to
/// @param cdata_ The encoded parameters of the delegate call encoded
function delegateCallAny(address target_, bytes memory cdata_) public payable onlyFactory {
assembly {
let size := mload(cdata_)
let ptr := add(0x20, cdata_)
if iszero(delegatecall(gas(), target_, ptr, size, 0x00, 0x00)) {
returndatacopy(0x00, 0x00, returndatasize())
revert(0x00, returndatasize())
}
}
function delegateCallAny(
address target_,
bytes memory cdata_
) public payable onlyFactory returns (bytes memory) {
return target_.functionDelegateCall(cdata_);
}
}
56 changes: 7 additions & 49 deletions bridge/contracts/Proxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ contract Proxy {
case 0xca11c0de11 {
// revert in case user is not factory/admin
if iszero(eq(caller(), factory)) {
revertUnauthorized()
revertASM("unauthorized", 12)
}
// if caller is factory, and has 0xca11c0de00<address> as calldata,
// run admin logic and return
setImplementationAddress()
}
default {
revertIncorrectDataOrFunctionSignature()
revertASM("function not found", 18)
}
}
}
Expand All @@ -80,58 +80,16 @@ contract Proxy {

///////////// Functions ///////////////

function revertUnauthorized() {
function revertASM(str, len) {
let ptr := mload(0x40)
let startPtr := ptr
mstore(ptr, hex"08c379a0") // keccak256('Error(string)')[0:4]
ptr := add(ptr, 0x4)
mstore(ptr, 0x20)
ptr := add(ptr, 0x20)
mstore(ptr, 12) // string length = 13
mstore(ptr, len) // string length
ptr := add(ptr, 0x20)
mstore(ptr, "unauthorized")
ptr := add(ptr, 0x20)
revert(startPtr, sub(ptr, startPtr))
}

function revertImplementationLock() {
let ptr := mload(0x40)
let startPtr := ptr
mstore(ptr, hex"08c379a0") // keccak256('Error(string)')[0:4]
ptr := add(ptr, 0x4)
mstore(ptr, 0x20)
ptr := add(ptr, 0x20)
mstore(ptr, 13) // string length = 13
ptr := add(ptr, 0x20)
mstore(ptr, "update locked")
ptr := add(ptr, 0x20)
revert(startPtr, sub(ptr, startPtr))
}

function revertImplementationNotSetYet() {
let ptr := mload(0x40)
let startPtr := ptr
mstore(ptr, hex"08c379a0") // keccak256('Error(string)')[0:4]
ptr := add(ptr, 0x4)
mstore(ptr, 0x20)
ptr := add(ptr, 0x20)
mstore(ptr, 13) // string length = 13
ptr := add(ptr, 0x20)
mstore(ptr, "logic not set")
ptr := add(ptr, 0x20)
revert(startPtr, sub(ptr, startPtr))
}

function revertIncorrectDataOrFunctionSignature() {
let ptr := mload(0x40)
let startPtr := ptr
mstore(ptr, hex"08c379a0") // keccak256('Error(string)')[0:4]
ptr := add(ptr, 0x4)
mstore(ptr, 0x20)
ptr := add(ptr, 0x20)
mstore(ptr, 18) // string length = 18
ptr := add(ptr, 0x20)
mstore(ptr, "function not found")
mstore(ptr, str)
ptr := add(ptr, 0x20)
revert(startPtr, sub(ptr, startPtr))
}
Expand All @@ -150,7 +108,7 @@ contract Proxy {
function setImplementationAddress() {
// check if the upgrade functionality is locked.
if eq(shr(160, sload(not(0x00))), 0xca11c0de15dead10deadc0de) {
revertImplementationLock()
revertASM("update locked", 13)
}
// this is an assignment to implementation
let newImpl := shr(96, shl(96, calldataload(0x05)))
Expand All @@ -164,7 +122,7 @@ contract Proxy {
function passthrough() {
let logicAddress := sload(not(0x00))
if iszero(logicAddress) {
revertImplementationNotSetYet()
revertASM("logic not set", 13)
}
// load free memory pointer
let ptr := mload(0x40)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ abstract contract BridgePoolFactoryBase is ImmutableFactory {
// solhint-disable-next-line
fallback() external {
address implementation_ = _implementation;
assembly {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, shl(176, 0x363d3d373d3d3d363d73)) //10
mstore(add(ptr, 10), shl(96, implementation_)) //20
Expand Down Expand Up @@ -84,7 +84,7 @@ abstract contract BridgePoolFactoryBase is ImmutableFactory {
bytes memory alicenetFactoryAddress = abi.encodePacked(
bytes32(uint256(uint160(_factoryAddress())))
);
assembly {
assembly ("memory-safe") {
let ptr := mload(0x40)
calldatacopy(ptr, deployCode_.offset, deployCode_.length)
// add bytes32 alicenet factory address as parameter to constructor
Expand Down Expand Up @@ -141,7 +141,7 @@ abstract contract BridgePoolFactoryBase is ImmutableFactory {
_implementation = implementation;
//check if the logic exists for the specified pool
uint256 implementationSize;
assembly {
assembly ("memory-safe") {
implementationSize := extcodesize(implementation)
}
if (implementationSize == 0) {
Expand All @@ -159,7 +159,7 @@ abstract contract BridgePoolFactoryBase is ImmutableFactory {
*/
function _deployStaticPool(bytes32 salt_) internal returns (address contractAddr) {
uint256 contractSize;
assembly {
assembly ("memory-safe") {
let ptr := mload(0x40)
mstore(ptr, shl(136, 0x5880818283335afa3d82833e3d82f3))
contractAddr := create2(0, ptr, 15, salt_)
Expand Down
60 changes: 30 additions & 30 deletions bridge/contracts/libraries/math/CryptoLibrary.sol
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,7 @@ library CryptoLibrary {
// *) y-coordinate of point Q

bool success;
assembly {
// solium-disable-line
assembly ("memory-safe") {
// 0x06 id of precompiled bn256Add contract
// 0 number of ether to transfer
// 128 size of call parameters, i.e. 128 bytes total
Expand All @@ -189,8 +188,7 @@ library CryptoLibrary {
// *) scalar x

bool success;
assembly {
// solium-disable-line
assembly ("memory-safe") {
// 0x07 id of precompiled bn256ScalarMul contract
// 0 number of ether to transfer
// 96 size of call parameters, i.e. 96 bytes total (256 bit for x, 256 bit for y, 256 bit for scalar)
Expand All @@ -205,8 +203,7 @@ library CryptoLibrary {
function bn128CheckPairing(uint256[12] memory input) internal view returns (bool) {
uint256[1] memory result;
bool success;
assembly {
// solium-disable-line
assembly ("memory-safe") {
// 0x08 id of precompiled bn256Pairing contract (checking the elliptic curve pairings)
// 0 number of ether to transfer
// 384 size of call parameters, i.e. 12*256 bits == 384 bytes
Expand All @@ -228,8 +225,7 @@ library CryptoLibrary {
// and slightly modified
function expmod(uint256 base, uint256 e, uint256 m) internal view returns (uint256 result) {
bool success;
assembly {
// solium-disable-line
assembly ("memory-safe") {
// define pointer
let p := mload(0x40)
// store data assembly-favouring ways
Expand Down Expand Up @@ -369,11 +365,24 @@ library CryptoLibrary {
/// HashToG1 takes byte slice message and outputs an element of G1. Optimized version of `hashToG1`
/// written in EVM assembly.
function hashToG1ASM(bytes memory message) internal view returns (uint256[2] memory h) {
assembly {
assembly ("memory-safe") {
function revertASM(str, len) {
let ptr := mload(0x40)
let startPtr := ptr
mstore(ptr, hex"08c379a0") // keccak256('Error(string)')[0:4]
ptr := add(ptr, 0x4)
mstore(ptr, 0x20)
ptr := add(ptr, 0x20)
mstore(ptr, len) // string length
ptr := add(ptr, 0x20)
mstore(ptr, str)
ptr := add(ptr, 0x20)
revert(startPtr, sub(ptr, startPtr))
}

function memCopy(dest, src, len) {
if lt(len, 32) {
mstore(0, "invalid len")
revert(0, 32)
revertASM("invalid length", 18)
}
// Copy word-length chunks while possible
for {
Expand Down Expand Up @@ -404,7 +413,7 @@ library CryptoLibrary {
memCopy(ptr, paramPtr, 0xb0)
let success := staticcall(gas(), 0x08, ptr, 384, ptr, 32)
if iszero(success) {
revert(0, 0)
revertASM("invalid bn128 pairing", 21)
}
result := mload(ptr)
}
Expand All @@ -426,8 +435,7 @@ library CryptoLibrary {
mstore(add(ptr, 0x60), alpha)
mstore(add(ptr, 0x80), P_MINUS2)
if iszero(staticcall(gas(), 0x05, ptr, 0xc0, fp, 0x20)) {
mstore(0, "exp mod failed at 1")
revert(0, 0x20)
revertASM("exp mod failed at 1", 19)
}
alpha := mload(fp)

Expand All @@ -445,8 +453,7 @@ library CryptoLibrary {
mstore(add(ptr, 0x80), P_PLUS1_OVER4)
mstore(add(ptr, 0x60), x_three)
if iszero(staticcall(gas(), 0x05, ptr, 0xc0, fp, 0x20)) {
mstore(0, "exp mod failed at 2")
revert(0, 0x20)
revertASM("exp mod failed at 2", 19)
}

let ymul := 1
Expand All @@ -467,8 +474,7 @@ library CryptoLibrary {
x_three := addmod(x_three, 3, FIELD_MODULUS)
mstore(add(ptr, 0x60), x_three)
if iszero(staticcall(gas(), 0x05, ptr, 0xc0, fp, 0x20)) {
mstore(0, "exp mod failed at 3")
revert(0, 0x20)
revertASM("exp mod failed at 3", 19)
}
y := mulmod(mload(fp), ymul, FIELD_MODULUS)
y_two := mulmod(y, y, FIELD_MODULUS)
Expand All @@ -489,8 +495,7 @@ library CryptoLibrary {
x_three := addmod(x_three, 3, FIELD_MODULUS)
mstore(add(ptr, 0x60), x_three)
if iszero(staticcall(gas(), 0x05, ptr, 0xc0, fp, 0x20)) {
mstore(0, "exp mod failed at 4")
revert(0, 0x20)
revertASM("exp mod failed at 4", 19)
}
y := mulmod(mload(fp), ymul, FIELD_MODULUS)
mstore(output, x)
Expand Down Expand Up @@ -519,35 +524,30 @@ library CryptoLibrary {
let y1 := mload(add(output, 0x20))
let success := bn128IsOnCurve(x1, y1)
if iszero(success) {
mstore(0, "x1 y1 not in curve")
revert(0, 0x20)
revertASM("x1 y1 not in curve", 18)
}
baseToG1(ptr, h2, output)
let x2 := mload(output)
let y2 := mload(add(output, 0x20))
success := bn128IsOnCurve(x2, y2)
if iszero(success) {
mstore(0, "x2 y2 not in curve")
revert(0, 0x20)
revertASM("x2 y2 not in curve", 18)
}
mstore(ptr, x1)
mstore(add(ptr, 0x20), y1)
mstore(add(ptr, 0x40), x2)
mstore(add(ptr, 0x60), y2)
if iszero(staticcall(gas(), 0x06, ptr, 128, ptr, 64)) {
mstore(0, "bn256 add failed")
revert(0, 0x20)
revertASM("bn256 add failed", 16)
}
let x := mload(ptr)
let y := mload(add(ptr, 0x20))
success := bn128IsOnCurve(x, y)
if iszero(success) {
mstore(0, "x2 y2 not in curve")
revert(0, 0x20)
revertASM("x y not in curve", 16)
}
if or(iszero(x), eq(y, 1)) {
mstore(0, "point not safe to sign")
revert(0, 0x20)
revertASM("point not safe to sign", 22)
}
mstore(output, x)
mstore(add(output, 0x20), y)
Expand Down
Loading