Skip to content

Commit

Permalink
Fixes source extraction from docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
erak committed Oct 23, 2019
1 parent abf1aa7 commit ec53899
Show file tree
Hide file tree
Showing 6 changed files with 267 additions and 258 deletions.
344 changes: 172 additions & 172 deletions docs/050-breaking-changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -292,27 +292,27 @@ Consider you have the following pre-0.5.0 contract already deployed:

::

// This will not compile with the current version of the compiler
pragma solidity ^0.4.25;
contract OldContract {
function someOldFunction(uint8 a) {
//...
}
function anotherOldFunction() constant returns (bool) {
//...
}
// ...
}
// This will not compile with the current version of the compiler
pragma solidity ^0.4.25;
contract OldContract {
function someOldFunction(uint8 a) {
//...
}
function anotherOldFunction() constant returns (bool) {
//...
}
// ...
}

This will no longer compile with Solidity v0.5.0. However, you can define a compatible interface for it:

::

pragma solidity >=0.5.0 <0.7.0;
interface OldContract {
function someOldFunction(uint8 a) external;
function anotherOldFunction() external returns (bool);
}
pragma solidity >=0.5.0 <0.7.0;
interface OldContract {
function someOldFunction(uint8 a) external;
function anotherOldFunction() external returns (bool);
}

Note that we did not declare ``anotherOldFunction`` to be ``view``, despite it being declared ``constant`` in the original
contract. This is due to the fact that starting with Solidity v0.5.0 ``staticcall`` is used to call ``view`` functions.
Expand All @@ -325,37 +325,37 @@ Given the interface defined above, you can now easily use the already deployed p

::

pragma solidity >=0.5.0 <0.7.0;
pragma solidity >=0.5.0 <0.7.0;

interface OldContract {
function someOldFunction(uint8 a) external;
function anotherOldFunction() external returns (bool);
}
interface OldContract {
function someOldFunction(uint8 a) external;
function anotherOldFunction() external returns (bool);
}

contract NewContract {
function doSomething(OldContract a) public returns (bool) {
a.someOldFunction(0x42);
return a.anotherOldFunction();
}
}
contract NewContract {
function doSomething(OldContract a) public returns (bool) {
a.someOldFunction(0x42);
return a.anotherOldFunction();
}
}

Similarly, pre-0.5.0 libraries can be used by defining the functions of the library without implementation and
supplying the address of the pre-0.5.0 library during linking (see :ref:`commandline-compiler` for how to use the
commandline compiler for linking):

::

pragma solidity >=0.5.0 <0.7.0;
pragma solidity >=0.5.0 <0.7.0;

library OldLibrary {
function someFunction(uint8 a) public returns(bool);
}
library OldLibrary {
function someFunction(uint8 a) public returns(bool);
}

contract NewContract {
function f(uint8 a) public returns (bool) {
return OldLibrary.someFunction(a);
}
}
contract NewContract {
function f(uint8 a) public returns (bool) {
return OldLibrary.someFunction(a);
}
}


Example
Expand All @@ -368,144 +368,144 @@ Old version:

::

// This will not compile
pragma solidity ^0.4.25;

contract OtherContract {
uint x;
function f(uint y) external {
x = y;
}
function() payable external {}
}

contract Old {
OtherContract other;
uint myNumber;

// Function mutability not provided, not an error.
function someInteger() internal returns (uint) { return 2; }

// Function visibility not provided, not an error.
// Function mutability not provided, not an error.
function f(uint x) returns (bytes) {
// Var is fine in this version.
var z = someInteger();
x += z;
// Throw is fine in this version.
if (x > 100)
throw;
bytes b = new bytes(x);
y = -3 >> 1;
// y == -1 (wrong, should be -2)
do {
x += 1;
if (x > 10) continue;
// 'Continue' causes an infinite loop.
} while (x < 11);
// Call returns only a Bool.
bool success = address(other).call("f");
if (!success)
revert();
else {
// Local variables could be declared after their use.
int y;
}
return b;
}

// No need for an explicit data location for 'arr'
function g(uint[] arr, bytes8 x, OtherContract otherContract) public {
otherContract.transfer(1 ether);

// Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
// the first 4 bytes of x will be lost. This might lead to
// unexpected behavior since bytesX are right padded.
uint32 y = uint32(x);
myNumber += y + msg.value;
}
}
// This will not compile
pragma solidity ^0.4.25;

contract OtherContract {
uint x;
function f(uint y) external {
x = y;
}
function() payable external {}
}

contract Old {
OtherContract other;
uint myNumber;

// Function mutability not provided, not an error.
function someInteger() internal returns (uint) { return 2; }

// Function visibility not provided, not an error.
// Function mutability not provided, not an error.
function f(uint x) returns (bytes) {
// Var is fine in this version.
var z = someInteger();
x += z;
// Throw is fine in this version.
if (x > 100)
throw;
bytes b = new bytes(x);
y = -3 >> 1;
// y == -1 (wrong, should be -2)
do {
x += 1;
if (x > 10) continue;
// 'Continue' causes an infinite loop.
} while (x < 11);
// Call returns only a Bool.
bool success = address(other).call("f");
if (!success)
revert();
else {
// Local variables could be declared after their use.
int y;
}
return b;
}

// No need for an explicit data location for 'arr'
function g(uint[] arr, bytes8 x, OtherContract otherContract) public {
otherContract.transfer(1 ether);

// Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
// the first 4 bytes of x will be lost. This might lead to
// unexpected behavior since bytesX are right padded.
uint32 y = uint32(x);
myNumber += y + msg.value;
}
}

New version:

::

pragma solidity >=0.5.0 <0.7.0;

contract OtherContract {
uint x;
function f(uint y) external {
x = y;
}
function() payable external {}
}

contract New {
OtherContract other;
uint myNumber;

// Function mutability must be specified.
function someInteger() internal pure returns (uint) { return 2; }

// Function visibility must be specified.
// Function mutability must be specified.
function f(uint x) public returns (bytes memory) {
// The type must now be explicitly given.
uint z = someInteger();
x += z;
// Throw is now disallowed.
require(x > 100);
int y = -3 >> 1;
// y == -2 (correct)
do {
x += 1;
if (x > 10) continue;
// 'Continue' jumps to the condition below.
} while (x < 11);

// Call returns (bool, bytes).
// Data location must be specified.
(bool success, bytes memory data) = address(other).call("f");
if (!success)
revert();
return data;
}

using address_make_payable for address;
// Data location for 'arr' must be specified
function g(uint[] memory arr, bytes8 x, OtherContract otherContract, address unknownContract) public payable {
// 'otherContract.transfer' is not provided.
// Since the code of 'OtherContract' is known and has the fallback
// function, address(otherContract) has type 'address payable'.
address(otherContract).transfer(1 ether);

// 'unknownContract.transfer' is not provided.
// 'address(unknownContract).transfer' is not provided
// since 'address(unknownContract)' is not 'address payable'.
// If the function takes an 'address' which you want to send
// funds to, you can convert it to 'address payable' via 'uint160'.
// Note: This is not recommended and the explicit type
// 'address payable' should be used whenever possible.
// To increase clarity, we suggest the use of a library for
// the conversion (provided after the contract in this example).
address payable addr = unknownContract.make_payable();
require(addr.send(1 ether));

// Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
// the conversion is not allowed.
// We need to convert to a common size first:
bytes4 x4 = bytes4(x); // Padding happens on the right
uint32 y = uint32(x4); // Conversion is consistent
// 'msg.value' cannot be used in a 'non-payable' function.
// We need to make the function payable
myNumber += y + msg.value;
}
}

// We can define a library for explicitly converting ``address``
// to ``address payable`` as a workaround.
library address_make_payable {
function make_payable(address x) internal pure returns (address payable) {
return address(uint160(x));
}
}
pragma solidity >=0.5.0 <0.7.0;

contract OtherContract {
uint x;
function f(uint y) external {
x = y;
}
function() payable external {}
}

contract New {
OtherContract other;
uint myNumber;

// Function mutability must be specified.
function someInteger() internal pure returns (uint) { return 2; }

// Function visibility must be specified.
// Function mutability must be specified.
function f(uint x) public returns (bytes memory) {
// The type must now be explicitly given.
uint z = someInteger();
x += z;
// Throw is now disallowed.
require(x > 100);
int y = -3 >> 1;
require(y == -2);
do {
x += 1;
if (x > 10) continue;
// 'Continue' jumps to the condition below.
} while (x < 11);

// Call returns (bool, bytes).
// Data location must be specified.
(bool success, bytes memory data) = address(other).call("f");
if (!success)
revert();
return data;
}

using address_make_payable for address;
// Data location for 'arr' must be specified
function g(uint[] memory /* arr */, bytes8 x, OtherContract otherContract, address unknownContract) public payable {
// 'otherContract.transfer' is not provided.
// Since the code of 'OtherContract' is known and has the fallback
// function, address(otherContract) has type 'address payable'.
address(otherContract).transfer(1 ether);

// 'unknownContract.transfer' is not provided.
// 'address(unknownContract).transfer' is not provided
// since 'address(unknownContract)' is not 'address payable'.
// If the function takes an 'address' which you want to send
// funds to, you can convert it to 'address payable' via 'uint160'.
// Note: This is not recommended and the explicit type
// 'address payable' should be used whenever possible.
// To increase clarity, we suggest the use of a library for
// the conversion (provided after the contract in this example).
address payable addr = unknownContract.make_payable();
require(addr.send(1 ether));

// Since uint32 (4 bytes) is smaller than bytes8 (8 bytes),
// the conversion is not allowed.
// We need to convert to a common size first:
bytes4 x4 = bytes4(x); // Padding happens on the right
uint32 y = uint32(x4); // Conversion is consistent
// 'msg.value' cannot be used in a 'non-payable' function.
// We need to make the function payable
myNumber += y + msg.value;
}
}

// We can define a library for explicitly converting ``address``
// to ``address payable`` as a workaround.
library address_make_payable {
function make_payable(address x) internal pure returns (address payable) {
return address(uint160(x));
}
}
Loading

0 comments on commit ec53899

Please sign in to comment.