Francisco Giordano 8 жил өмнө
parent
commit
c7636bdc4c

+ 22 - 0
contracts/token/SafeERC20.sol

@@ -0,0 +1,22 @@
+pragma solidity ^0.4.11;
+
+import './ERC20Basic.sol';
+import './ERC20.sol';
+
+/**
+ * @title SafeERC20
+ * @dev Wrappers around ERC20 operations that throw on failure.
+ */
+library SafeERC20 {
+  function safeTransfer(ERC20Basic token, address to, uint256 value) internal {
+    assert(token.transfer(to, value));
+  }
+
+  function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
+    assert(token.transferFrom(from, to, value));
+  }
+
+  function safeApprove(ERC20 token, address spender, uint256 value) internal {
+    assert(token.approve(spender, value));
+  }
+}

+ 27 - 0
test/SafeERC20.js

@@ -0,0 +1,27 @@
+import EVMThrow from './helpers/EVMThrow';
+
+require('chai')
+  .use(require('chai-as-promised'))
+  .should();
+
+const SafeERC20Helper = artifacts.require('./helpers/SafeERC20Helper.sol');
+
+contract('SafeERC20', function () {
+
+  beforeEach(async function () {
+    this.helper = await SafeERC20Helper.new();
+  });
+
+  it('should throw on failed transfer', async function () {
+    await this.helper.doFailingTransfer().should.be.rejectedWith(EVMThrow);
+  });
+
+  it('should throw on failed transferFrom', async function () {
+    await this.helper.doFailingTransferFrom().should.be.rejectedWith(EVMThrow);
+  });
+
+  it('should throw on failed approve', async function () {
+    await this.helper.doFailingApprove().should.be.rejectedWith(EVMThrow);
+  });
+
+});

+ 48 - 0
test/helpers/SafeERC20Helper.sol

@@ -0,0 +1,48 @@
+pragma solidity ^0.4.11;
+
+import '../../contracts/token/ERC20.sol';
+import '../../contracts/token/SafeERC20.sol';
+
+contract ERC20FailingMock is ERC20 {
+  function transfer(address, uint256) returns (bool) {
+    return false;
+  }
+
+  function transferFrom(address, address, uint256) returns (bool) {
+    return false;
+  }
+
+  function approve(address, uint256) returns (bool) {
+    return false;
+  }
+
+  function balanceOf(address) constant returns (uint256) {
+    return 0;
+  }
+
+  function allowance(address, address) constant returns (uint256) {
+    return 0;
+  }
+}
+
+contract SafeERC20Helper {
+  using SafeERC20 for ERC20;
+
+  ERC20 token;
+
+  function SafeERC20Helper() {
+    token = new ERC20FailingMock();
+  }
+
+  function doFailingTransfer() {
+    token.safeTransfer(0, 0);
+  }
+
+  function doFailingTransferFrom() {
+    token.safeTransferFrom(0, 0, 0);
+  }
+
+  function doFailingApprove() {
+    token.safeApprove(0, 0);
+  }
+}