Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.

Commit 8c7ca7a

Browse files
authored
Merge pull request #73 from SetProtocol/brian/require_successful_transfer
Brian/require successful transfer
2 parents f04712d + 21b551c commit 8c7ca7a

File tree

11 files changed

+610
-24
lines changed

11 files changed

+610
-24
lines changed

contracts/core/SetToken.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pragma solidity 0.4.24;
1818

1919

2020
import { DetailedERC20 } from "zeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol";
21-
import { ERC20 } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
2221
import { StandardToken } from "zeppelin-solidity/contracts/token/ERC20/StandardToken.sol";
2322
import { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol";
2423
import { ISetFactory } from "./interfaces/ISetFactory.sol";

contracts/core/TransferProxy.sol

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ pragma solidity 0.4.24;
1818

1919

2020
import { Authorizable } from "../lib/Authorizable.sol";
21-
import { ERC20 } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
2221
import { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol";
22+
import { ERC20Wrapper } from "./lib/ERC20Wrapper.sol";
2323

2424

2525
/**
@@ -80,17 +80,25 @@ contract TransferProxy is
8080
onlyAuthorized
8181
{
8282
// Retrieve current balance of token for the vault
83-
uint existingVaultBalance = ERC20(_tokenAddress).balanceOf(vaultAddress);
83+
uint existingVaultBalance = ERC20Wrapper.balanceOf(
84+
_tokenAddress,
85+
vaultAddress
86+
);
8487

8588
// Call specified ERC20 contract to transfer tokens from user to Vault (via proxy).
86-
ERC20(_tokenAddress).transferFrom(
89+
90+
ERC20Wrapper.transferFrom(
91+
_tokenAddress,
8792
_from,
8893
vaultAddress,
8994
_quantity
9095
);
9196

9297
// Verify transfer quantity is reflected in balance
93-
uint newVaultBalance = ERC20(_tokenAddress).balanceOf(vaultAddress);
98+
uint newVaultBalance = ERC20Wrapper.balanceOf(
99+
_tokenAddress,
100+
vaultAddress
101+
);
94102
require(newVaultBalance == existingVaultBalance.add(_quantity));
95103
}
96104
}

contracts/core/Vault.sol

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ pragma solidity 0.4.24;
1818

1919

2020
import { Authorizable } from "../lib/Authorizable.sol";
21-
import { ERC20 } from "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
2221
import { SafeMath } from "zeppelin-solidity/contracts/math/SafeMath.sol";
22+
import { ERC20Wrapper } from "./lib/ERC20Wrapper.sol";
2323

2424

2525
/**
@@ -92,16 +92,23 @@ contract Vault is
9292
isValidDestination(_to)
9393
{
9494
// Retrieve current balance of token for the vault
95-
uint existingVaultBalance = ERC20(_tokenAddress).balanceOf(this);
95+
uint existingVaultBalance = ERC20Wrapper.balanceOf(
96+
_tokenAddress,
97+
this
98+
);
9699

97100
// Call specified ERC20 token contract to transfer tokens from Vault to user
98-
ERC20(_tokenAddress).transfer(
101+
ERC20Wrapper.transfer(
102+
_tokenAddress,
99103
_to,
100104
_quantity
101105
);
102106

103107
// Verify transfer quantity is reflected in balance
104-
uint newVaultBalance = ERC20(_tokenAddress).balanceOf(this);
108+
uint newVaultBalance = ERC20Wrapper.balanceOf(
109+
_tokenAddress,
110+
this
111+
);
105112
require(newVaultBalance == existingVaultBalance.sub(_quantity));
106113
}
107114

@@ -154,7 +161,7 @@ contract Vault is
154161
}
155162

156163
/* ============ Getter Functions ============ */
157-
164+
158165
/*
159166
* Get balance of particular contract for owner.
160167
*
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*
2+
Copyright 2018 Set Labs Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
pragma solidity 0.4.24;
18+
19+
import { IERC20 } from "../../lib/IERC20.sol";
20+
21+
22+
/**
23+
* @title TokenInteract
24+
* @author Set Protocol
25+
*
26+
* This library contains functions for interacting wtih ERC20 tokens, even those not fully compliant.
27+
* For all functions we will only accept tokens that return a null or true value, any other values will
28+
* cause the operation to revert.
29+
*/
30+
library ERC20Wrapper {
31+
32+
// ============ Constants ============
33+
34+
string constant INVALID_RETURN_VALUE_TRANSFER = "Transferred token does not return null or true on successful trasnfer.";
35+
string constant INVALID_RETURN_VALUE_TRANSFERFROM = "Transferred token does not return null or true on successful transferFrom.";
36+
37+
// ============ Internal Functions ============
38+
39+
function balanceOf(
40+
address _tokenAddress,
41+
address _ownerAddress
42+
)
43+
internal
44+
view
45+
returns (uint256)
46+
{
47+
return IERC20(_tokenAddress).balanceOf(_ownerAddress);
48+
}
49+
50+
function transfer(
51+
address _tokenAddress,
52+
address _to,
53+
uint256 _quantity
54+
)
55+
internal
56+
{
57+
IERC20(_tokenAddress).transfer(_to, _quantity);
58+
59+
require(
60+
checkSuccess(),
61+
INVALID_RETURN_VALUE_TRANSFER
62+
);
63+
}
64+
65+
function transferFrom(
66+
address _tokenAddress,
67+
address _from,
68+
address _to,
69+
uint256 _quantity
70+
)
71+
internal
72+
{
73+
IERC20(_tokenAddress).transferFrom(_from, _to, _quantity);
74+
75+
require(
76+
checkSuccess(),
77+
INVALID_RETURN_VALUE_TRANSFERFROM
78+
);
79+
}
80+
81+
// ============ Private Functions ============
82+
83+
/**
84+
* Checks the return value of the previous function up to 32 bytes. Returns true if the previous
85+
* function returned 0 bytes or 1.
86+
*/
87+
function checkSuccess(
88+
)
89+
private
90+
pure
91+
returns (bool)
92+
{
93+
// default to failure
94+
uint256 returnValue = 0;
95+
96+
assembly {
97+
// check number of bytes returned from last function call
98+
switch returndatasize
99+
100+
// no bytes returned: assume success
101+
case 0x0 {
102+
returnValue := 1
103+
}
104+
105+
// 32 bytes returned
106+
case 0x20 {
107+
// copy 32 bytes into scratch space
108+
returndatacopy(0x0, 0x0, 0x20)
109+
110+
// load those bytes into returnValue
111+
returnValue := mload(0x0)
112+
}
113+
114+
// not sure what was returned: dont mark as success
115+
default { }
116+
}
117+
118+
// check if returned value is one or nothing
119+
return returnValue == 1;
120+
}
121+
}

contracts/lib/Authorizable.sol

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import { Ownable } from "zeppelin-solidity/contracts/ownership/Ownable.sol";
2626
* The Authorizable contract is an inherited contract that sets permissions on certain function calls
2727
* through the onlyAuthorized modifier. Permissions can be managed only by the Owner of the contract.
2828
*/
29-
3029
contract Authorizable is
3130
Ownable
3231
{

contracts/lib/IERC20.sol

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
Copyright 2018 Set Labs Inc.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
pragma solidity 0.4.24;
18+
19+
20+
/**
21+
* @title GeneralERC20
22+
* @author Set Protocol
23+
*
24+
* Interface for using ERC20 Tokens. This interface is needed to interact with tokens that are not
25+
* fully ERC20 compliant and return something other than true on successful transfers.
26+
*/
27+
interface IERC20 {
28+
function balanceOf(
29+
address _owner
30+
)
31+
external
32+
view
33+
returns (uint256);
34+
35+
function transfer(
36+
address _to,
37+
uint256 _quantity
38+
)
39+
external;
40+
41+
function transferFrom(
42+
address _from,
43+
address _to,
44+
uint256 _quantity
45+
)
46+
external;
47+
}

0 commit comments

Comments
 (0)