Created
November 23, 2018 12:22
-
-
Save tomw1808/553852dd7975d171ca3cfd68a2b7ae94 to your computer and use it in GitHub Desktop.
Breaking Changes From Solidity 0.5.0
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
pragma solidity 0.5.0; | |
contract SolidityChanges { | |
/** | |
* https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html#semantic-and-syntactic-changes | |
* | |
* The functions .call(), .delegatecall(), staticcall(), | |
* keccak256(), sha256() and ripemd160() now accept only | |
* a single bytes argument. Moreover, the argument is | |
* not padded. This was changed to make more explicit | |
* and clear how the arguments are concatenated. Change | |
* every .call() (and family) to a .call("") and every | |
* .call(signature, a, b, c) to use | |
* .call(abi.encodeWithSignature(signature, a, b, c)) | |
* (the last one only works for value types). Change every | |
* keccak256(a, b, c) to keccak256(abi.encodePacked(a, b, c)). | |
* Even though it is not a breaking change, it is suggested | |
* that developers change | |
* x.call(bytes4(keccak256("f(uint256)"), a, b) to | |
* x.call(abi.encodeWithSignature("f(uint256)", a, b)). | |
* */ | |
function callTest(address otherContract) public{ | |
(bool success,) = otherContract.call(abi.encodeWithSignature("updateMyVar(uint256)",5)); | |
require(success); | |
} | |
/** | |
* https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html#semantic-and-syntactic-changes | |
* | |
* Functions .call(), .delegatecall() and .staticcall() now return (bool, bytes memory) | |
* to provide access to the return data. Change bool success = otherContract.call("f") | |
* to (bool success, bytes memory data) = otherContract.call("f"). | |
* */ | |
function callWithReturnTest(address otherContract) public returns(bytes memory){ | |
(bool success, bytes memory memoryData) = otherContract.call(abi.encodeWithSignature("updateWithReturn(uint256)",5)); | |
require(success); | |
return memoryData; | |
} | |
/** | |
* Explicit function visibility is now mandatory. Add public to every | |
* function and constructor, and external to every fallback or | |
* interface function that does not specify its visibility already. | |
* */ | |
function () external { | |
} | |
/** | |
* Explicit data location for all variables of struct, array or mapping | |
* types is now mandatory. This is also applied to function parameters | |
* and return variables. For example, change uint[] x = m_x to | |
* uint[] storage x = m_x, and | |
* function f(uint[][] x) to | |
* function f(uint[][] memory x) | |
* where memory is the data location and might be replaced by storage | |
* or calldata accordingly. Note that external functions require | |
* parameters with a data location of calldata. | |
* */ | |
uint[] public myUint; | |
function overwriteUintArray(uint[] memory _myUint) public { | |
myUint = _myUint; | |
} | |
/** | |
* Contract types do not include address members anymore in order to | |
* separate the namespaces. Therefore, it is now necessary to | |
* explicitly convert values of contract type to addresses before | |
* using an address member. Example: if c is a contract, | |
* change | |
* c.transfer(...) to | |
* address(c).transfer(...), and | |
* c.balance to | |
* address(c).balance. | |
* */ | |
function getTheBalanceOf(OtherContract addressOtherContract) public view returns(uint) { | |
return address(addressOtherContract).balance; | |
} | |
/** | |
* The address type was split into address and address payable, where | |
* only address payable provides the transfer function. An address | |
* payable can be directly converted to an address, but the other | |
* way around is not allowed. Converting address to address payable is | |
* possible via conversion through uint160. If c is a contract, | |
* address(c) results in address payable only if c has a payable fallback | |
* function. If you use the withdraw pattern, you most likely do not | |
* have to change your code because transfer is only used on msg.sender | |
* instead of stored addresses and msg.sender is an address payable. | |
* */ | |
function deposit() public payable { | |
//we save the msg.value somewhere | |
} | |
function withdraw(address payable _receiver) public { | |
_receiver.transfer(address(this).balance); | |
} | |
function destroyMe() public { | |
selfdestruct(msg.sender); | |
} | |
} | |
contract OtherContract { | |
uint myVar; | |
event CalledFunction(uint newVar); | |
function updateMyVar(uint _someUint) public { | |
myVar =_someUint; | |
emit CalledFunction(_someUint); | |
} | |
function updateWithReturn(uint _someUint) public returns(uint){ | |
myVar =_someUint; | |
emit CalledFunction(_someUint); | |
return myVar; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This was really helpful. Thank you :)