-
Notifications
You must be signed in to change notification settings - Fork 12k
Safe Casting Library from uint256 to uintXX #1926
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
Merged
nventuro
merged 19 commits into
OpenZeppelin:master
from
bh2smith:safecasting/adresses#1925
Oct 22, 2019
Merged
Changes from 2 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
bccf91c
Include Safe Casting Library with complete and exhaustive test-suite.
bh2smith d11968a
linting test file.
bh2smith 9eaa5d8
Typo in SafeCast import statement
bh2smith 891c66f
Update test/utils/SafeCast.test.js
bh2smith 535a64b
Rename `castUXX` to `toUintXX` from suggestion
bh2smith bdb2162
Merge branch 'safecasting/adresses#1925' of github.com:bh2smith/openz…
bh2smith 75486ae
Merge branch 'master' into safecasting/adresses#1925
bh2smith bfbe418
Tackling the quick and easy suggestions regarding error string improv…
bh2smith e0dd08b
Merge branch 'safecasting/adresses#1925' of github.com:bh2smith/openz…
bh2smith 7ca0192
typo and changelog update.
bh2smith b0ac5db
Improve SafeCast tests
nventuro f538218
Update test/utils/SafeCast.test.js
bh2smith e613a4e
Update test/utils/SafeCast.test.js
bh2smith d26d4b3
Merge branch 'master' into safecasting/adresses#1925
bh2smith 9fe42fb
Merge branch 'master' into safecasting/adresses#1925
bh2smith 650383b
incorrect import
bh2smith 4826041
add SafeCast to docs site
frangio 60bbffc
Update CHANGELOG.md
nventuro 773e635
Update SafeCast.sol
nventuro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,27 @@ | ||
pragma solidity ^0.5.0; | ||
|
||
import "../util/SafeCast.sol"; | ||
|
||
contract SafeCastMock { | ||
using SafeCast for uint; | ||
|
||
function castU128(uint a) public pure returns (uint128) { | ||
return a.castU128(); | ||
} | ||
|
||
function castU64(uint a) public pure returns (uint64) { | ||
return a.castU64(); | ||
} | ||
|
||
function castU32(uint a) public pure returns (uint32) { | ||
return a.castU32(); | ||
} | ||
|
||
function castU16(uint a) public pure returns (uint16) { | ||
return a.castU16(); | ||
} | ||
|
||
function castU8(uint a) public pure returns (uint8) { | ||
return a.castU8(); | ||
} | ||
} |
This file contains hidden or 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,88 @@ | ||
pragma solidity ^0.5.0; | ||
|
||
|
||
/** | ||
* @dev Wrappers over Solidity's uintXX casting operators with added overflow | ||
* checks. | ||
* | ||
* Downcasting from uint256 in Solidity does not revert by default on overflow. | ||
* This can easily result in undesired exploitation or bugs, since developers | ||
* usually assume that overflows raise errors. `SafeCast` restores this intuition | ||
* by reverting the transaction when such an operation overflows. | ||
* | ||
* Using this library instead of the unchecked operations eliminates an entire | ||
* class of bugs, so it's recommended to use it always. | ||
*/ | ||
library SafeCast { | ||
|
||
/** | ||
* @dev Returns the downcasted uint128 from uint256, reverting on | ||
* overflow (when the input is greater than largest uint128). | ||
* | ||
* Counterpart to Solidity's `uint128` operator. | ||
* | ||
* Requirements: | ||
* - input cannot overflow. | ||
*/ | ||
function castU128(uint a) internal pure returns (uint128) { | ||
require(a < 2**128, "SafeCast: downcast overflow"); | ||
bh2smith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return uint128(a); | ||
} | ||
|
||
/** | ||
* @dev Returns the downcasted uint64 from uint256, reverting on | ||
* overflow (when the input is greater than largest uint64). | ||
* | ||
* Counterpart to Solidity's `uint64` operator. | ||
* | ||
* Requirements: | ||
* - input cannot overflow. | ||
bh2smith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
*/ | ||
function castU64(uint a) internal pure returns (uint64) { | ||
require(a < 2**64, "SafeCast: downcast overflow"); | ||
bh2smith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return uint64(a); | ||
} | ||
|
||
/** | ||
* @dev Returns the downcasted uint32 from uint256, reverting on | ||
* overflow (when the input is greater than largest uint32). | ||
* | ||
* Counterpart to Solidity's `uint32` operator. | ||
* | ||
* Requirements: | ||
* - input cannot overflow. | ||
*/ | ||
function castU32(uint a) internal pure returns (uint32) { | ||
require(a < 2**32, "SafeCast: downcast overflow"); | ||
return uint32(a); | ||
} | ||
|
||
/** | ||
* @dev Returns the downcasted uint16 from uint256, reverting on | ||
* overflow (when the input is greater than largest uint16). | ||
* | ||
* Counterpart to Solidity's `uint16` operator. | ||
* | ||
* Requirements: | ||
* - input cannot overflow. | ||
*/ | ||
function castU16(uint a) internal pure returns (uint16) { | ||
require(a < 2**16, "SafeCast: downcast overflow"); | ||
return uint16(a); | ||
} | ||
|
||
/** | ||
* @dev Returns the downcasted uint8 from uint256, reverting on | ||
* overflow (when the input is greater than largest uint8). | ||
* | ||
* Counterpart to Solidity's `uint8` operator. | ||
* | ||
* Requirements: | ||
* - input cannot overflow. | ||
*/ | ||
function castU8(uint a) internal pure returns (uint8) { | ||
|
||
bh2smith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
require(a < 2**8, "SafeCast: downcast overflow"); | ||
return uint8(a); | ||
} | ||
} |
This file contains hidden or 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,81 @@ | ||
const SafeCastMock = artifacts.require('SafeCastMock'); | ||
|
||
bh2smith marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const { expectRevert } = require('openzeppelin-test-helpers'); | ||
|
||
contract('SafeCast', async (accounts) => { | ||
describe('castU128()', () => { | ||
it('reverts on overflow (i.e. input >= 2^128)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
await expectRevert( | ||
contract.castU128('340282366920938463463374607431768211456'), | ||
'SafeCast: downcast overflow' | ||
); | ||
await expectRevert( | ||
contract.castU128('999340282366920938463463374607431768211455'), | ||
'SafeCast: downcast overflow' | ||
); | ||
}); | ||
it('passes where appropriate (i.e. 0 <= input < 2^128)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
assert.equal(await contract.castU128(0), 0); | ||
assert.equal(await contract.castU128(1), 1); | ||
assert.equal( | ||
(await contract.castU128('340282366920938463463374607431768211455')).toString(), | ||
'340282366920938463463374607431768211455' | ||
); | ||
}); | ||
}); | ||
describe('castU64()', () => { | ||
it('reverts on overflow (i.e. input >= 2^64)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
await expectRevert(contract.castU64('18446744073709551616'), 'SafeCast: downcast overflow'); | ||
await expectRevert(contract.castU64('18446744073709551617'), 'SafeCast: downcast overflow'); | ||
}); | ||
it('passes where appropriate (i.e. 0 <= input < 2^64)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
assert.equal(await contract.castU64(0), 0); | ||
assert.equal(await contract.castU64(1), 1); | ||
assert.equal((await contract.castU64('18446744073709551615')).toString(), '18446744073709551615'); | ||
}); | ||
}); | ||
describe('castU32()', () => { | ||
it('reverts on overflow (i.e. input >= 2^32)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
await expectRevert(contract.castU32('4294967296'), 'SafeCast: downcast overflow'); | ||
await expectRevert(contract.castU32('4294967297'), 'SafeCast: downcast overflow'); | ||
}); | ||
it('passes where appropriate (i.e. 0 <= input < 2^32)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
assert.equal(await contract.castU32(0), 0); | ||
assert.equal(await contract.castU32(1), 1); | ||
assert.equal(await contract.castU32(4294967295), 4294967295); | ||
}); | ||
}); | ||
describe('castU16()', () => { | ||
it('reverts on overflow (i.e. input >= 2^16)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
await expectRevert(contract.castU16('65536'), 'SafeCast: downcast overflow'); | ||
await expectRevert(contract.castU16('65537'), 'SafeCast: downcast overflow'); | ||
}); | ||
|
||
it('passes where appropriate (i.e. 0 <= input < 2^16)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
assert.equal(await contract.castU16(0), 0); | ||
assert.equal(await contract.castU16(1), 1); | ||
assert.equal(await contract.castU16(65535), 65535); | ||
}); | ||
}); | ||
describe('castU8()', () => { | ||
it('reverts on overflow (i.e. input >= 2^8)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
await expectRevert(contract.castU8(256), 'SafeCast: downcast overflow'); | ||
await expectRevert(contract.castU8(257), 'SafeCast: downcast overflow'); | ||
}); | ||
it('passes where appropriate (i.e. 0 <= input < 2^8)', async () => { | ||
const contract = await SafeCastMock.new(); | ||
assert.equal(await contract.castU8(0), 0); | ||
assert.equal(await contract.castU8(1), 1); | ||
assert.equal(await contract.castU8(255), 255); | ||
}); | ||
}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.