From 711cece7ea829622e24d11f7470e0cc51b999f8d Mon Sep 17 00:00:00 2001 From: mattia richetto Date: Sun, 6 Jan 2019 15:00:00 -0800 Subject: [PATCH 1/2] add test and clean --- src/clean.js | 2 +- tests/Proxy/Proxy.sol | 52 +++++++++ tests/Proxy/__snapshots__/jsfmt.spec.js.snap | 106 +++++++++++++++++++ tests/Proxy/jsfmt.spec.js | 1 + 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 tests/Proxy/Proxy.sol create mode 100644 tests/Proxy/__snapshots__/jsfmt.spec.js.snap create mode 100644 tests/Proxy/jsfmt.spec.js diff --git a/src/clean.js b/src/clean.js index 7e130534b..9aa8fee8a 100644 --- a/src/clean.js +++ b/src/clean.js @@ -1,6 +1,6 @@ // eslint-disable-next-line no-unused-vars const clean = (ast, newObj, parent) => { - ['code', 'codeStart', 'loc', 'range'].forEach(name => { + ['code', 'codeStart', 'loc', 'operations', 'range'].forEach(name => { delete newObj[name]; // eslint-disable-line no-param-reassign }); }; diff --git a/tests/Proxy/Proxy.sol b/tests/Proxy/Proxy.sol new file mode 100644 index 000000000..3f737797f --- /dev/null +++ b/tests/Proxy/Proxy.sol @@ -0,0 +1,52 @@ +pragma solidity ^0.4.24; + +/** + * @title Proxy + * @dev Gives the possibility to delegate any call to a foreign implementation. + */ +contract Proxy { + + /** + * @dev Tells the address of the implementation where every call will be delegated. + * @return address of the implementation to which it will be delegated + */ + function _implementation() internal view returns (address); + + /** + * @dev Fallback function. + * Implemented entirely in `_fallback`. + */ + function _fallback() internal { + _delegate(_implementation()); + } + + /** + * @dev Fallback function allowing to perform a delegatecall to the given implementation. + * This function will return whatever the implementation call returns + */ + function _delegate(address implementation) internal { + /*solium-disable-next-line security/no-inline-assembly*/ + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize) + + switch result + // delegatecall returns 0 on error. + case 0 { revert(0, returndatasize) } + default { return(0, returndatasize) } + } + } + + function () public payable { + _fallback(); + } +} diff --git a/tests/Proxy/__snapshots__/jsfmt.spec.js.snap b/tests/Proxy/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 000000000..eb60a3d31 --- /dev/null +++ b/tests/Proxy/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,106 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Proxy.sol 1`] = ` +pragma solidity ^0.4.24; + +/** + * @title Proxy + * @dev Gives the possibility to delegate any call to a foreign implementation. + */ +contract Proxy { + + /** + * @dev Tells the address of the implementation where every call will be delegated. + * @return address of the implementation to which it will be delegated + */ + function _implementation() internal view returns (address); + + /** + * @dev Fallback function. + * Implemented entirely in \`_fallback\`. + */ + function _fallback() internal { + _delegate(_implementation()); + } + + /** + * @dev Fallback function allowing to perform a delegatecall to the given implementation. + * This function will return whatever the implementation call returns + */ + function _delegate(address implementation) internal { + /*solium-disable-next-line security/no-inline-assembly*/ + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize) + + switch result + // delegatecall returns 0 on error. + case 0 { revert(0, returndatasize) } + default { return(0, returndatasize) } + } + } + + function () public payable { + _fallback(); + } +} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +pragma solidity ^0.4.24; + +/** + * @title Proxy + * @dev Gives the possibility to delegate any call to a foreign implementation. + */ +contract Proxy { + /** + * @dev Tells the address of the implementation where every call will be delegated. + * @return address of the implementation to which it will be delegated + */ + function _implementation() internal view returns (address); + + /** + * @dev Fallback function. + * Implemented entirely in \`_fallback\`. + */ + function _fallback() internal { + _delegate(_implementation()); + } + + /** + * @dev Fallback function allowing to perform a delegatecall to the given implementation. + * This function will return whatever the implementation call returns + */ + function _delegate(address implementation) internal { + /*solium-disable-next-line security/no-inline-assembly*/ + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize) + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) + // Copy the returned data. + returndatacopy(0, 0, returndatasize) + switch result + // delegatecall returns 0 on error. + case 0 {} + default {} + } + } + + function() public payable { + _fallback(); + } +} + +`; diff --git a/tests/Proxy/jsfmt.spec.js b/tests/Proxy/jsfmt.spec.js new file mode 100644 index 000000000..989047bcc --- /dev/null +++ b/tests/Proxy/jsfmt.spec.js @@ -0,0 +1 @@ +run_spec(__dirname); From fc761afe284cdc75921bbb61c223285e56eb9834 Mon Sep 17 00:00:00 2001 From: fvictorio Date: Mon, 7 Jan 2019 14:55:35 -0300 Subject: [PATCH 2/2] Update snapshots and re-add operations to AST check --- src/clean.js | 2 +- tests/Proxy/__snapshots__/jsfmt.spec.js.snap | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/clean.js b/src/clean.js index 9aa8fee8a..7e130534b 100644 --- a/src/clean.js +++ b/src/clean.js @@ -1,6 +1,6 @@ // eslint-disable-next-line no-unused-vars const clean = (ast, newObj, parent) => { - ['code', 'codeStart', 'loc', 'operations', 'range'].forEach(name => { + ['code', 'codeStart', 'loc', 'range'].forEach(name => { delete newObj[name]; // eslint-disable-line no-param-reassign }); }; diff --git a/tests/Proxy/__snapshots__/jsfmt.spec.js.snap b/tests/Proxy/__snapshots__/jsfmt.spec.js.snap index eb60a3d31..a5f677cd0 100644 --- a/tests/Proxy/__snapshots__/jsfmt.spec.js.snap +++ b/tests/Proxy/__snapshots__/jsfmt.spec.js.snap @@ -92,9 +92,13 @@ contract Proxy { // Copy the returned data. returndatacopy(0, 0, returndatasize) switch result - // delegatecall returns 0 on error. - case 0 {} - default {} + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize) + } + default { + return(0, returndatasize) + } } }