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

Unsigned conversion #2111 #2123

Merged
merged 14 commits into from
Mar 27, 2020
Merged
5 changes: 5 additions & 0 deletions contracts/mocks/SafeCastMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import "../utils/SafeCast.sol";

contract SafeCastMock {
using SafeCast for uint;
using SafeCast for int;

function toUint256(int a) public pure returns (uint256) {
return a.toUint256();
}

function toUint128(uint a) public pure returns (uint128) {
return a.toUint128();
Expand Down
13 changes: 13 additions & 0 deletions contracts/utils/SafeCast.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,17 @@ library SafeCast {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}

/**
* @dev Returns the unsigned uint256 from int256, reverting if
* the input is negative.
*
* Requirements:
*
* - input must be greater or equal than 0.
pepelu marked this conversation as resolved.
Show resolved Hide resolved
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: negative value cannot be cast to uint256");
pepelu marked this conversation as resolved.
Show resolved Hide resolved
return uint256(value);
}
}
49 changes: 49 additions & 0 deletions test/utils/SafeCast.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,54 @@ describe('SafeCast', async () => {
});
}

function testSignedToUint (bits) {
describe(`toUint${bits}`, () => {
const maxValue = new BN('2').pow(new BN(bits)).subn(1);
const minValue = new BN('2').pow(new BN(bits - 1));

it('downcasts 0', async function () {
expect(await this.safeCast[`toUint${bits}`](0)).to.be.bignumber.equal('0');
});

it('downcasts 1', async function () {
expect(await this.safeCast[`toUint${bits}`](1)).to.be.bignumber.equal('1');
});

it(`downcasts -2^${bits - 1} - 1 (${minValue.subn(1)})`, async function () {
expect(await this.safeCast[`toUint${bits}`](minValue.subn(1))).to.be.bignumber.equal(minValue.subn(1));
});

it('reverts when downcasting -1', async function () {
await expectRevert(
this.safeCast[`toUint${bits}`](-1),
`SafeCast: negative value cannot be cast to uint${bits}`
);
});

it(`reverts when downcasting 2^${bits} - 1 (-1 in Two's complement)`, async function () {
await expectRevert(
this.safeCast[`toUint${bits}`](maxValue),
`SafeCast: negative value cannot be cast to uint${bits}`
);
});

it(`reverts when downcasting 2^${bits - 1} (-${minValue})`, async function () {
await expectRevert(
this.safeCast[`toUint${bits}`](minValue),
`SafeCast: negative value cannot be cast to uint${bits}`
);
});

it(`reverts when downcasting -2^${bits - 1} (-${minValue})`, async function () {
await expectRevert(
this.safeCast[`toUint${bits}`](minValue.neg()),
`SafeCast: negative value cannot be cast to uint${bits}`
);
});
});
}

[8, 16, 32, 64, 128].forEach(bits => testToUint(bits));
pepelu marked this conversation as resolved.
Show resolved Hide resolved

[256].forEach(bits => testSignedToUint(bits));
});