-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add AaveDebtIssuanceModule contract * Module designed to issue/redeem SetTokens which hold one or more aTokens as components. * Refactor integration tests * Moved validation logic to IssuanceUtils library * Fix compilation bugs * Fix imports * Refactor IssuanceUtils library contract * Add new function which considers external positions * Rename functions * Refactor DebtIssuanceModuleV2 contract * Override _resolveDebtPositions function * Use new IssuanceUtils library contract * Improve javadocs * Add IssuanceUtils mock contract * Refactor _setQuantity parameter in both library functions * Add standard token with rounding error mock * Returns a variable balance of value based on the error value set * Will be helpful to mock the behaviour of aTokens * Add tests for Debt issuance module V2 contract * Skip ALM <> DIM integration tests * Make validation logic statelesss * Earlier we were assuming that burn takes place before and mint takes place after the validation logic is called. But these assumptions make the validation logic stateful, which is not ideal. By removing those assumptions and passing in the required value from outside the function, the validation logic becomes stateless, which allows it to be used at multiple places flexibly. * The validation functions now perform just the check. All required state to perform the check is passed from outside. * Add external debt position to SetToken in tests * Improve coverage: Add tests for issue/redeem quantity is 0 * Rename IssuanceUtils to IssuanceValidationUtils * Update docs to specify redeem requires transferring in debt from caller * Add more tests and improve existing ones * Newly added tests are an EXACT copy of the tests for DebtIssuanceModule. Only difference is this SetToken contains tokenWithRoundingError instead of weth as a default position. This is to ensure the DebtIssuanceModuleV2 behaves exactly similar to DebtIssuanceModule when there is no rounding error present in it's constituent components. * Existing tests are improved by introducing fees and by different revert messages for different reverts * Add more tests and optimize tests to complete faster * Bump package to 0.0.52
- Loading branch information
Showing
11 changed files
with
1,452 additions
and
20 deletions.
There are no files selected for viewing
This file contains 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,180 @@ | ||
/* | ||
Copyright 2020 Set Labs Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
SPDX-License-Identifier: Apache License, Version 2.0 | ||
*/ | ||
|
||
pragma solidity 0.6.10; | ||
|
||
import "./StandardTokenMock.sol"; | ||
import "@openzeppelin/contracts/math/SignedSafeMath.sol"; | ||
import "@openzeppelin/contracts/math/SafeMath.sol"; | ||
import "@openzeppelin/contracts/utils/SafeCast.sol"; | ||
|
||
contract StandardTokenWithRoundingErrorMock { | ||
using SignedSafeMath for int256; | ||
using SafeCast for int256; | ||
using SafeMath for uint256; | ||
event Transfer( | ||
address indexed from, | ||
address indexed to, | ||
uint256 value | ||
); | ||
|
||
event Approval( | ||
address indexed owner, | ||
address indexed spender, | ||
uint256 value | ||
); | ||
|
||
uint256 constant public decimals = 18; | ||
string public name; | ||
string public symbol; | ||
int256 public err; | ||
|
||
mapping (address => uint256) public _balances; | ||
|
||
mapping (address => mapping (address => uint256)) public _allowed; | ||
|
||
uint256 public _totalSupply; | ||
|
||
|
||
constructor( | ||
address _initialAccount, | ||
uint256 _initialBalance, | ||
int256 _err, | ||
string memory _name, | ||
string memory _symbol, | ||
uint8 _decimals | ||
) | ||
public | ||
|
||
{ | ||
_balances[_initialAccount] = _initialBalance; | ||
_totalSupply = _initialBalance; | ||
name = _name; | ||
symbol = _symbol; | ||
err = _err; | ||
} | ||
|
||
/** | ||
* @dev Returns balance of owner with the rounding error applied | ||
* @param owner address whose balance is to be returned | ||
*/ | ||
function balanceOf(address owner) external view returns (uint256) { | ||
uint256 balance = _balances[owner]; | ||
if (err >= 0) { | ||
return balance.add(err.toUint256()); | ||
} else { | ||
uint256 absoluteError = err.mul(-1).toUint256(); | ||
if (balance >= absoluteError) { | ||
return balance.sub(absoluteError); | ||
} else { | ||
return 0; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @dev Transfer tokens from one address to another | ||
* @param _from address The address which you want to send tokens from | ||
* @param _to address The address which you want to transfer to | ||
* @param _value uint256 the amount of tokens to be transferred | ||
*/ | ||
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) { | ||
require(_to != address(0), "to null"); | ||
require(_value <= _balances[_from], "value greater than from balance"); | ||
require(_value <= _allowed[_from][msg.sender], "value greater than allowed"); | ||
|
||
_balances[_from] = _balances[_from].sub(_value); | ||
_balances[_to] = _balances[_to].add(_value); | ||
_allowed[_from][msg.sender] = _allowed[_from][msg.sender].sub(_value); | ||
emit Transfer(_from, _to, _value); | ||
return true; | ||
} | ||
|
||
/** | ||
* @dev Transfer tokens from one address to another | ||
* @param _to The address to transfer to. | ||
* @param _value The amount to be transferred. | ||
*/ | ||
function transfer(address _to, uint256 _value) external returns (bool) { | ||
require(_to != address(0), "to null"); | ||
require(_value <= _balances[msg.sender], "value greater than sender balance"); | ||
|
||
_balances[msg.sender] = _balances[msg.sender].sub(_value); | ||
_balances[_to] = _balances[_to].add(_value); | ||
emit Transfer(msg.sender, _to, _value); | ||
return true; | ||
} | ||
|
||
function setError(int256 _err) external returns (bool) { | ||
err = _err; | ||
return true; | ||
} | ||
|
||
function totalSupply() external view returns (uint256) { | ||
return _totalSupply; | ||
} | ||
|
||
function allowance( | ||
address owner, | ||
address spender | ||
) | ||
external | ||
view | ||
returns (uint256) | ||
{ | ||
return _allowed[owner][spender]; | ||
} | ||
|
||
function approve(address spender, uint256 value) external returns (bool) { | ||
require(spender != address(0)); | ||
|
||
_allowed[msg.sender][spender] = value; | ||
emit Approval(msg.sender, spender, value); | ||
return true; | ||
} | ||
|
||
function increaseAllowance( | ||
address spender, | ||
uint256 addedValue | ||
) | ||
external | ||
returns (bool) | ||
{ | ||
require(spender != address(0)); | ||
|
||
_allowed[msg.sender][spender] = ( | ||
_allowed[msg.sender][spender].add(addedValue)); | ||
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); | ||
return true; | ||
} | ||
|
||
function decreaseAllowance( | ||
address spender, | ||
uint256 subtractedValue | ||
) | ||
external | ||
returns (bool) | ||
{ | ||
require(spender != address(0)); | ||
|
||
_allowed[msg.sender][spender] = ( | ||
_allowed[msg.sender][spender].sub(subtractedValue)); | ||
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]); | ||
return true; | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
contracts/mocks/protocol/lib/IssuanceValidationUtilsMock.sol
This file contains 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,58 @@ | ||
/* | ||
Copyright 2021 Set Labs Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
SPDX-License-Identifier: Apache License, Version 2.0 | ||
*/ | ||
|
||
pragma solidity 0.6.10; | ||
|
||
import { ISetToken } from "../../../interfaces/ISetToken.sol"; | ||
import { IssuanceValidationUtils } from "../../../protocol/lib/IssuanceValidationUtils.sol"; | ||
|
||
contract IssuanceValidationUtilsMock { | ||
/* ============ External Functions ============ */ | ||
|
||
function testValidateCollateralizationPostTransferInPreHook( | ||
ISetToken _setToken, | ||
address _component, | ||
uint256 _initialSetSupply, | ||
uint256 _componentQuantity | ||
) | ||
external | ||
view | ||
{ | ||
IssuanceValidationUtils.validateCollateralizationPostTransferInPreHook( | ||
_setToken, | ||
_component, | ||
_initialSetSupply, | ||
_componentQuantity | ||
); | ||
} | ||
|
||
function testValidateCollateralizationPostTransferOut( | ||
ISetToken _setToken, | ||
address _component, | ||
uint256 _finalSetSupply | ||
) | ||
external | ||
view | ||
{ | ||
IssuanceValidationUtils.validateCollateralizationPostTransferOut( | ||
_setToken, | ||
_component, | ||
_finalSetSupply | ||
); | ||
} | ||
} |
This file contains 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,93 @@ | ||
/* | ||
Copyright 2021 Set Labs Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
SPDX-License-Identifier: Apache License, Version 2.0 | ||
*/ | ||
|
||
pragma solidity 0.6.10; | ||
|
||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import { SafeCast } from "@openzeppelin/contracts/utils/SafeCast.sol"; | ||
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; | ||
|
||
import { ISetToken } from "../../interfaces/ISetToken.sol"; | ||
import { PreciseUnitMath } from "../../lib/PreciseUnitMath.sol"; | ||
|
||
/** | ||
* @title IssuanceValidationUtils | ||
* @author Set Protocol | ||
* | ||
* A collection of utility functions to help during issuance/redemption of SetToken. | ||
*/ | ||
library IssuanceValidationUtils { | ||
using SafeMath for uint256; | ||
using SafeCast for int256; | ||
using PreciseUnitMath for uint256; | ||
|
||
/** | ||
* Validates component transfer IN to SetToken during issuance/redemption. Reverts if Set is undercollateralized post transfer. | ||
* NOTE: Call this function immediately after transfer IN but before calling external hooks (if any). | ||
* | ||
* @param _setToken Instance of the SetToken being issued/redeemed | ||
* @param _component Address of component being transferred in/out | ||
* @param _initialSetSupply Initial SetToken supply before issuance/redemption | ||
* @param _componentQuantity Amount of component transferred into SetToken | ||
*/ | ||
function validateCollateralizationPostTransferInPreHook( | ||
ISetToken _setToken, | ||
address _component, | ||
uint256 _initialSetSupply, | ||
uint256 _componentQuantity | ||
) | ||
internal | ||
view | ||
{ | ||
uint256 newComponentBalance = IERC20(_component).balanceOf(address(_setToken)); | ||
|
||
uint256 defaultPositionUnit = _setToken.getDefaultPositionRealUnit(address(_component)).toUint256(); | ||
|
||
require( | ||
// Use preciseMulCeil to increase the lower bound and maintain over-collateralization | ||
newComponentBalance >= _initialSetSupply.preciseMulCeil(defaultPositionUnit).add(_componentQuantity), | ||
"Invalid transfer in. Results in undercollateralization" | ||
); | ||
} | ||
|
||
/** | ||
* Validates component transfer OUT of SetToken during issuance/redemption. Reverts if Set is undercollateralized post transfer. | ||
* | ||
* @param _setToken Instance of the SetToken being issued/redeemed | ||
* @param _component Address of component being transferred in/out | ||
* @param _finalSetSupply Final SetToken supply after issuance/redemption | ||
*/ | ||
function validateCollateralizationPostTransferOut( | ||
ISetToken _setToken, | ||
address _component, | ||
uint256 _finalSetSupply | ||
) | ||
internal | ||
view | ||
{ | ||
uint256 newComponentBalance = IERC20(_component).balanceOf(address(_setToken)); | ||
|
||
uint256 defaultPositionUnit = _setToken.getDefaultPositionRealUnit(address(_component)).toUint256(); | ||
|
||
require( | ||
// Use preciseMulCeil to increase lower bound and maintain over-collateralization | ||
newComponentBalance >= _finalSetSupply.preciseMulCeil(defaultPositionUnit), | ||
"Invalid transfer out. Results in undercollateralization" | ||
); | ||
} | ||
} |
This file contains 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
Oops, something went wrong.