mirror of
https://github.com/Instadapp/dsa-connectors-old.git
synced 2024-07-29 22:47:46 +00:00
Merge pull request #7 from InstaDApp/synthetix-connector
Synthetix connector
This commit is contained in:
commit
3c1ab740c9
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
*.sol linguist-language=Solidity
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -58,5 +58,8 @@ Thumbs.db
|
||||||
.com.apple.timemachine.donotpresent
|
.com.apple.timemachine.donotpresent
|
||||||
|
|
||||||
# truffle
|
# truffle
|
||||||
|
|
||||||
build/contracts
|
build/contracts
|
||||||
|
|
||||||
|
# buidler
|
||||||
|
artifacts
|
||||||
|
cache
|
||||||
|
|
11
buidler.config.js
Normal file
11
buidler.config.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
usePlugin("@nomiclabs/buidler-truffle5");
|
||||||
|
// You have to export an object to set up your config
|
||||||
|
// This object can have the following optional entries:
|
||||||
|
// defaultNetwork, networks, solc, and paths.
|
||||||
|
// Go to https://buidler.dev/config/ to learn more
|
||||||
|
module.exports = {
|
||||||
|
// This is a sample solc configuration that specifies which version of solc to use
|
||||||
|
solc: {
|
||||||
|
version: "0.6.2",
|
||||||
|
},
|
||||||
|
};
|
|
@ -36,14 +36,14 @@ contract Stores {
|
||||||
/**
|
/**
|
||||||
* @dev Set Uint value in InstaMemory Contract.
|
* @dev Set Uint value in InstaMemory Contract.
|
||||||
*/
|
*/
|
||||||
function setUint(uint setId, uint val) internal {
|
function setUint(uint setId, uint val) virtual internal {
|
||||||
if (setId != 0) MemoryInterface(getMemoryAddr()).setUint(setId, val);
|
if (setId != 0) MemoryInterface(getMemoryAddr()).setUint(setId, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev emit event on event contract
|
* @dev emit event on event contract
|
||||||
*/
|
*/
|
||||||
function emitEvent(bytes32 eventCode, bytes memory eventData) internal {
|
function emitEvent(bytes32 eventCode, bytes memory eventData) virtual internal {
|
||||||
(uint model, uint id) = connectorID();
|
(uint model, uint id) = connectorID();
|
||||||
EventInterface(getEventAddr()).emitEvent(model, id, eventCode, eventData);
|
EventInterface(getEventAddr()).emitEvent(model, id, eventCode, eventData);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pragma solidity ^0.6.0;
|
pragma solidity ^0.6.0;
|
||||||
|
|
||||||
import "../../node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
// import files from common directory
|
// import files from common directory
|
||||||
import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol";
|
import { TokenInterface , MemoryInterface, EventInterface} from "../common/interfaces.sol";
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
pragma solidity ^0.6.0;
|
pragma solidity ^0.6.0;
|
||||||
pragma experimental ABIEncoderV2;
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import "../../node_modules/@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
|
||||||
|
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
|
||||||
interface LiqudityInterface {
|
interface LiqudityInterface {
|
||||||
function deposit(address, uint) external payable;
|
function deposit(address, uint) external payable;
|
||||||
|
|
194
contracts/connectors/synthetix.sol
Normal file
194
contracts/connectors/synthetix.sol
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
// import files from common directory
|
||||||
|
import { TokenInterface } from "../common/interfaces.sol";
|
||||||
|
import { Stores } from "../common/stores.sol";
|
||||||
|
import { DSMath } from "../common/math.sol";
|
||||||
|
|
||||||
|
interface IStakingRewards {
|
||||||
|
function stake(uint256 amount) external;
|
||||||
|
function withdraw(uint256 amount) external;
|
||||||
|
function getReward() external;
|
||||||
|
function balanceOf(address) external view returns(uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SynthetixMapping {
|
||||||
|
struct StakingData {
|
||||||
|
address stakingPool;
|
||||||
|
address stakingToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
function stakingMapping(bytes32) external view returns(StakingData memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract SynthetixStakingHelper is DSMath, Stores {
|
||||||
|
/**
|
||||||
|
* @dev Return InstaDApp Synthetix Mapping Addresses
|
||||||
|
*/
|
||||||
|
function getMappingAddr() internal virtual view returns (address) {
|
||||||
|
return 0xe81F70Cc7C0D46e12d70efc60607F16bbD617E88; // InstaMapping Address
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Return Synthetix Token address.
|
||||||
|
*/
|
||||||
|
function getSnxAddr() internal virtual view returns (address) {
|
||||||
|
return 0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Convert String to bytes32.
|
||||||
|
*/
|
||||||
|
function stringToBytes32(string memory str) internal pure returns (bytes32 result) {
|
||||||
|
require(bytes(str).length != 0, "string-empty");
|
||||||
|
// solium-disable-next-line security/no-inline-assembly
|
||||||
|
assembly {
|
||||||
|
result := mload(add(str, 32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Get staking data
|
||||||
|
*/
|
||||||
|
function getStakingData(string memory stakingName)
|
||||||
|
internal
|
||||||
|
virtual
|
||||||
|
view
|
||||||
|
returns (
|
||||||
|
IStakingRewards stakingContract,
|
||||||
|
TokenInterface stakingToken,
|
||||||
|
bytes32 stakingType
|
||||||
|
)
|
||||||
|
{
|
||||||
|
stakingType = stringToBytes32(stakingName);
|
||||||
|
SynthetixMapping.StakingData memory stakingData = SynthetixMapping(getMappingAddr()).stakingMapping(stakingType);
|
||||||
|
require(stakingData.stakingPool != address(0) && stakingData.stakingToken != address(0), "Wrong Staking Name");
|
||||||
|
stakingContract = IStakingRewards(stakingData.stakingPool);
|
||||||
|
stakingToken = TokenInterface(stakingData.stakingToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract SynthetixStaking is SynthetixStakingHelper {
|
||||||
|
event LogDeposit(
|
||||||
|
address token,
|
||||||
|
bytes32 stakingType,
|
||||||
|
uint256 amount,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogWithdraw(
|
||||||
|
address token,
|
||||||
|
bytes32 stakingType,
|
||||||
|
uint256 amount,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
);
|
||||||
|
|
||||||
|
event LogClaimedReward(
|
||||||
|
address token,
|
||||||
|
bytes32 stakingType,
|
||||||
|
uint256 rewardAmt,
|
||||||
|
uint setId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Deposit Token.
|
||||||
|
* @param stakingPoolName staking token address.
|
||||||
|
* @param amt staking token amount.
|
||||||
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
||||||
|
* @param setId Set token amount at this ID in `InstaMemory` Contract.
|
||||||
|
*/
|
||||||
|
function deposit(
|
||||||
|
string calldata stakingPoolName,
|
||||||
|
uint amt,
|
||||||
|
uint getId,
|
||||||
|
uint setId
|
||||||
|
) external payable {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
(IStakingRewards stakingContract, TokenInterface stakingToken, bytes32 stakingType) = getStakingData(stakingPoolName);
|
||||||
|
_amt = _amt == uint(-1) ? stakingToken.balanceOf(address(this)) : _amt;
|
||||||
|
|
||||||
|
stakingToken.approve(address(stakingContract), _amt);
|
||||||
|
stakingContract.stake(_amt);
|
||||||
|
|
||||||
|
setUint(setId, _amt);
|
||||||
|
emit LogDeposit(address(stakingToken), stakingType, _amt, getId, setId);
|
||||||
|
bytes32 _eventCode = keccak256("LogDeposit(address,bytes32,uint256,uint256,uint256)");
|
||||||
|
bytes memory _eventParam = abi.encode(address(stakingToken), stakingType, _amt, getId, setId);
|
||||||
|
emitEvent(_eventCode, _eventParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Withdraw Token.
|
||||||
|
* @param stakingPoolName staking token address.
|
||||||
|
* @param amt staking token amount.
|
||||||
|
* @param getId Get token amount at this ID from `InstaMemory` Contract.
|
||||||
|
* @param setIdAmount Set token amount at this ID in `InstaMemory` Contract.
|
||||||
|
* @param setIdReward Set reward amount at this ID in `InstaMemory` Contract.
|
||||||
|
*/
|
||||||
|
function withdraw(
|
||||||
|
string calldata stakingPoolName,
|
||||||
|
uint amt,
|
||||||
|
uint getId,
|
||||||
|
uint setIdAmount,
|
||||||
|
uint setIdReward
|
||||||
|
) external payable {
|
||||||
|
uint _amt = getUint(getId, amt);
|
||||||
|
(IStakingRewards stakingContract, TokenInterface stakingToken, bytes32 stakingType) = getStakingData(stakingPoolName);
|
||||||
|
|
||||||
|
TokenInterface snxToken = TokenInterface(getSnxAddr());
|
||||||
|
|
||||||
|
_amt = _amt == uint(-1) ? stakingContract.balanceOf(address(this)) : _amt;
|
||||||
|
uint intialBal = snxToken.balanceOf(address(this));
|
||||||
|
stakingContract.withdraw(_amt);
|
||||||
|
stakingContract.getReward();
|
||||||
|
uint finalBal = snxToken.balanceOf(address(this));
|
||||||
|
|
||||||
|
uint rewardAmt = sub(finalBal, intialBal);
|
||||||
|
|
||||||
|
setUint(setIdAmount, _amt);
|
||||||
|
setUint(setIdReward, rewardAmt);
|
||||||
|
|
||||||
|
emit LogWithdraw(address(stakingToken), stakingType, _amt, getId, setIdAmount);
|
||||||
|
bytes32 _eventCodeWithdraw = keccak256("LogWithdraw(address,bytes32,uint256,uint256,uint256)");
|
||||||
|
bytes memory _eventParamWithdraw = abi.encode(address(stakingToken), _amt, getId, setIdAmount);
|
||||||
|
emitEvent(_eventCodeWithdraw, _eventParamWithdraw);
|
||||||
|
|
||||||
|
emit LogClaimedReward(address(stakingToken), stakingType, rewardAmt, setIdReward);
|
||||||
|
bytes32 _eventCodeReward = keccak256("LogClaimedReward(address,bytes32,uint256,uint256)");
|
||||||
|
bytes memory _eventParamReward = abi.encode(address(stakingToken), rewardAmt, setIdReward);
|
||||||
|
emitEvent(_eventCodeReward, _eventParamReward);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Claim Reward.
|
||||||
|
* @param stakingPoolName staking token address.
|
||||||
|
* @param setId Set reward amount at this ID in `InstaMemory` Contract.
|
||||||
|
*/
|
||||||
|
function claimReward(
|
||||||
|
string calldata stakingPoolName,
|
||||||
|
uint setId
|
||||||
|
) external payable {
|
||||||
|
(IStakingRewards stakingContract, TokenInterface stakingToken, bytes32 stakingType) = getStakingData(stakingPoolName);
|
||||||
|
|
||||||
|
TokenInterface snxToken = TokenInterface(getSnxAddr());
|
||||||
|
|
||||||
|
uint intialBal = snxToken.balanceOf(address(this));
|
||||||
|
stakingContract.getReward();
|
||||||
|
uint finalBal = snxToken.balanceOf(address(this));
|
||||||
|
|
||||||
|
uint rewardAmt = sub(finalBal, intialBal);
|
||||||
|
|
||||||
|
setUint(setId, rewardAmt);
|
||||||
|
emit LogClaimedReward(address(stakingToken), stakingType, rewardAmt, setId);
|
||||||
|
bytes32 _eventCode = keccak256("LogClaimedReward(address,bytes32,uint256,uint256)");
|
||||||
|
bytes memory _eventParam = abi.encode(address(stakingToken), stakingType, rewardAmt, setId);
|
||||||
|
emitEvent(_eventCode, _eventParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract ConnectSynthetixStaking is SynthetixStaking {
|
||||||
|
string public name = "synthetix-staking-v1";
|
||||||
|
}
|
95
contracts/mapping/staking.sol
Normal file
95
contracts/mapping/staking.sol
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
interface ConnectorsInterface {
|
||||||
|
function chief(address) external view returns (bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IndexInterface {
|
||||||
|
function master() external view returns (address);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract BytesHelper {
|
||||||
|
/**
|
||||||
|
* @dev Convert String to bytes32.
|
||||||
|
*/
|
||||||
|
function stringToBytes32(string memory str) internal pure returns (bytes32 result) {
|
||||||
|
require(bytes(str).length != 0, "String-Empty");
|
||||||
|
// solium-disable-next-line security/no-inline-assembly
|
||||||
|
assembly {
|
||||||
|
result := mload(add(str, 32))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Convert bytes32 to String.
|
||||||
|
*/
|
||||||
|
function bytes32ToString(bytes32 _bytes32) internal pure returns (string memory) {
|
||||||
|
bytes32 _temp;
|
||||||
|
uint count;
|
||||||
|
for (uint256 i; i < 32; i++) {
|
||||||
|
_temp = _bytes32[i];
|
||||||
|
if( _temp != bytes32(0)) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes memory bytesArray = new bytes(count);
|
||||||
|
for (uint256 i; i < count; i++) {
|
||||||
|
bytesArray[i] = (_bytes32[i]);
|
||||||
|
}
|
||||||
|
return (string(bytesArray));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contract Helpers is BytesHelper {
|
||||||
|
address public constant connectors = 0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c;
|
||||||
|
address public constant instaIndex = 0x2971AdFa57b20E5a416aE5a708A8655A9c74f723;
|
||||||
|
uint public version = 1;
|
||||||
|
|
||||||
|
mapping (bytes32 => StakingData) public stakingMapping;
|
||||||
|
|
||||||
|
struct StakingData {
|
||||||
|
address stakingPool;
|
||||||
|
address stakingToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
event LogAddStakingMapping(string stakingName, bytes32 stakingType, address stakingAddress, address stakingToken);
|
||||||
|
event LogRemoveStakingMapping(string stakingName, bytes32 stakingType, address stakingAddress, address stakingToken);
|
||||||
|
|
||||||
|
modifier isChief virtual {
|
||||||
|
require(
|
||||||
|
ConnectorsInterface(connectors).chief(msg.sender) ||
|
||||||
|
IndexInterface(instaIndex).master() == msg.sender, "not-Chief");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStakingMapping(string memory stakingName, address stakingAddress, address stakingToken) public isChief {
|
||||||
|
require(stakingAddress != address(0), "stakingAddress-not-vaild");
|
||||||
|
require(stakingToken != address(0), "stakingToken-not-vaild");
|
||||||
|
require(bytes(stakingName).length <= 32, "Length-exceeds");
|
||||||
|
bytes32 stakeType = stringToBytes32(stakingName);
|
||||||
|
require(stakingMapping[stakeType].stakingPool == address(0), "StakingPool-already-added");
|
||||||
|
require(stakingMapping[stakeType].stakingToken == address(0), "StakingToken-already-added");
|
||||||
|
|
||||||
|
stakingMapping[stakeType] = StakingData(
|
||||||
|
stakingAddress,
|
||||||
|
stakingToken
|
||||||
|
);
|
||||||
|
emit LogAddStakingMapping(stakingName, stakeType, stakingAddress, stakingToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStakingMapping(string memory stakingName, address stakingAddress) public isChief {
|
||||||
|
require(stakingAddress != address(0), "stakingAddress-not-vaild");
|
||||||
|
bytes32 stakeType = stringToBytes32(stakingName);
|
||||||
|
require(stakingMapping[stakeType].stakingPool != address(0), "StakingPool-not-added-yet");
|
||||||
|
require(stakingMapping[stakeType].stakingToken != address(0), "StakingToken-not-added-yet");
|
||||||
|
require(stakingMapping[stakeType].stakingPool == stakingAddress, "different-staking-pool");
|
||||||
|
|
||||||
|
emit LogRemoveStakingMapping(stakingName, stakeType, stakingAddress, stakingMapping[stakeType].stakingToken);
|
||||||
|
delete stakingMapping[stakeType];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contract InstaMapping is Helpers {
|
||||||
|
string constant public name = "Synthetix-Mapping-v1";
|
||||||
|
}
|
7
contracts/tests/MockInstaMapping.sol
Normal file
7
contracts/tests/MockInstaMapping.sol
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
|
||||||
|
import { InstaMapping } from "../mapping/staking.sol";
|
||||||
|
|
||||||
|
contract MockInstaMapping is InstaMapping {
|
||||||
|
modifier isChief override {_;}
|
||||||
|
}
|
26
contracts/tests/MockSynthetix.sol
Normal file
26
contracts/tests/MockSynthetix.sol
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
import { ConnectSynthetixStaking } from "../connectors/synthetix.sol";
|
||||||
|
|
||||||
|
contract MockSynthetixStaking is ConnectSynthetixStaking{
|
||||||
|
address public synthetixStakingAddr;
|
||||||
|
address public instaMappingAddr;
|
||||||
|
|
||||||
|
constructor(address _synthetixStakingAddr, address _instaMappingAddr) public {
|
||||||
|
synthetixStakingAddr = _synthetixStakingAddr;
|
||||||
|
instaMappingAddr = _instaMappingAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function emitEvent(bytes32 eventCode, bytes memory eventData) override internal {}
|
||||||
|
|
||||||
|
function getSnxAddr() override internal view returns (address) {
|
||||||
|
return synthetixStakingAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMappingAddr() override internal view returns (address) {
|
||||||
|
return instaMappingAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUint(uint setId, uint val) override internal {}
|
||||||
|
}
|
373
contracts/tests/Mocks.sol
Normal file
373
contracts/tests/Mocks.sol
Normal file
|
@ -0,0 +1,373 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
|
||||||
|
interface MockInterface {
|
||||||
|
/**
|
||||||
|
* @dev After calling this method, the mock will return `response` when it is called
|
||||||
|
* with any calldata that is not mocked more specifically below
|
||||||
|
* (e.g. using givenMethodReturn).
|
||||||
|
* @param response ABI encoded response that will be returned if method is invoked
|
||||||
|
*/
|
||||||
|
function givenAnyReturn(bytes calldata response) external;
|
||||||
|
function givenAnyReturnBool(bool response) external;
|
||||||
|
function givenAnyReturnUint(uint response) external;
|
||||||
|
function givenAnyReturnAddress(address response) external;
|
||||||
|
|
||||||
|
function givenAnyRevert() external;
|
||||||
|
function givenAnyRevertWithMessage(string calldata message) external;
|
||||||
|
function givenAnyRunOutOfGas() external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev After calling this method, the mock will return `response` when the given
|
||||||
|
* methodId is called regardless of arguments. If the methodId and arguments
|
||||||
|
* are mocked more specifically (using `givenMethodAndArguments`) the latter
|
||||||
|
* will take precedence.
|
||||||
|
* @param method ABI encoded methodId. It is valid to pass full calldata (including arguments). The mock will extract the methodId from it
|
||||||
|
* @param response ABI encoded response that will be returned if method is invoked
|
||||||
|
*/
|
||||||
|
function givenMethodReturn(bytes calldata method, bytes calldata response) external;
|
||||||
|
function givenMethodReturnBool(bytes calldata method, bool response) external;
|
||||||
|
function givenMethodReturnUint(bytes calldata method, uint response) external;
|
||||||
|
function givenMethodReturnAddress(bytes calldata method, address response) external;
|
||||||
|
|
||||||
|
function givenMethodRevert(bytes calldata method) external;
|
||||||
|
function givenMethodRevertWithMessage(bytes calldata method, string calldata message) external;
|
||||||
|
function givenMethodRunOutOfGas(bytes calldata method) external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev After calling this method, the mock will return `response` when the given
|
||||||
|
* methodId is called with matching arguments. These exact calldataMocks will take
|
||||||
|
* precedence over all other calldataMocks.
|
||||||
|
* @param call ABI encoded calldata (methodId and arguments)
|
||||||
|
* @param response ABI encoded response that will be returned if contract is invoked with calldata
|
||||||
|
*/
|
||||||
|
function givenCalldataReturn(bytes calldata call, bytes calldata response) external;
|
||||||
|
function givenCalldataReturnBool(bytes calldata call, bool response) external;
|
||||||
|
function givenCalldataReturnUint(bytes calldata call, uint response) external;
|
||||||
|
function givenCalldataReturnAddress(bytes calldata call, address response) external;
|
||||||
|
|
||||||
|
function givenCalldataRevert(bytes calldata call) external;
|
||||||
|
function givenCalldataRevertWithMessage(bytes calldata call, string calldata message) external;
|
||||||
|
function givenCalldataRunOutOfGas(bytes calldata call) external;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Returns the number of times anything has been called on this mock since last reset
|
||||||
|
*/
|
||||||
|
function invocationCount() external returns (uint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Returns the number of times the given method has been called on this mock since last reset
|
||||||
|
* @param method ABI encoded methodId. It is valid to pass full calldata (including arguments). The mock will extract the methodId from it
|
||||||
|
*/
|
||||||
|
function invocationCountForMethod(bytes calldata method) external returns (uint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Returns the number of times this mock has been called with the exact calldata since last reset.
|
||||||
|
* @param call ABI encoded calldata (methodId and arguments)
|
||||||
|
*/
|
||||||
|
function invocationCountForCalldata(bytes calldata call) external returns (uint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Resets all mocked methods and invocation counts.
|
||||||
|
*/
|
||||||
|
function reset() external;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the MockInterface.
|
||||||
|
*/
|
||||||
|
contract MockContract is MockInterface {
|
||||||
|
enum MockType { Return, Revert, OutOfGas }
|
||||||
|
|
||||||
|
bytes32 public constant MOCKS_LIST_START = hex"01";
|
||||||
|
bytes public constant MOCKS_LIST_END = "0xff";
|
||||||
|
bytes32 public constant MOCKS_LIST_END_HASH = keccak256(MOCKS_LIST_END);
|
||||||
|
bytes4 public constant SENTINEL_ANY_MOCKS = hex"01";
|
||||||
|
bytes public constant DEFAULT_FALLBACK_VALUE = abi.encode(false);
|
||||||
|
|
||||||
|
// A linked list allows easy iteration and inclusion checks
|
||||||
|
mapping(bytes32 => bytes) calldataMocks;
|
||||||
|
mapping(bytes => MockType) calldataMockTypes;
|
||||||
|
mapping(bytes => bytes) calldataExpectations;
|
||||||
|
mapping(bytes => string) calldataRevertMessage;
|
||||||
|
mapping(bytes32 => uint) calldataInvocations;
|
||||||
|
|
||||||
|
mapping(bytes4 => bytes4) methodIdMocks;
|
||||||
|
mapping(bytes4 => MockType) methodIdMockTypes;
|
||||||
|
mapping(bytes4 => bytes) methodIdExpectations;
|
||||||
|
mapping(bytes4 => string) methodIdRevertMessages;
|
||||||
|
mapping(bytes32 => uint) methodIdInvocations;
|
||||||
|
|
||||||
|
MockType fallbackMockType;
|
||||||
|
bytes fallbackExpectation = DEFAULT_FALLBACK_VALUE;
|
||||||
|
string fallbackRevertMessage;
|
||||||
|
uint invocations;
|
||||||
|
uint resetCount;
|
||||||
|
|
||||||
|
constructor() public {
|
||||||
|
calldataMocks[MOCKS_LIST_START] = MOCKS_LIST_END;
|
||||||
|
methodIdMocks[SENTINEL_ANY_MOCKS] = SENTINEL_ANY_MOCKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackCalldataMock(bytes memory call) private {
|
||||||
|
bytes32 callHash = keccak256(call);
|
||||||
|
if (calldataMocks[callHash].length == 0) {
|
||||||
|
calldataMocks[callHash] = calldataMocks[MOCKS_LIST_START];
|
||||||
|
calldataMocks[MOCKS_LIST_START] = call;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function trackMethodIdMock(bytes4 methodId) private {
|
||||||
|
if (methodIdMocks[methodId] == 0x0) {
|
||||||
|
methodIdMocks[methodId] = methodIdMocks[SENTINEL_ANY_MOCKS];
|
||||||
|
methodIdMocks[SENTINEL_ANY_MOCKS] = methodId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _givenAnyReturn(bytes memory response) internal {
|
||||||
|
fallbackMockType = MockType.Return;
|
||||||
|
fallbackExpectation = response;
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyReturn(bytes calldata response) override external {
|
||||||
|
_givenAnyReturn(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyReturnBool(bool response) override external {
|
||||||
|
uint flag = response ? 1 : 0;
|
||||||
|
_givenAnyReturn(uintToBytes(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyReturnUint(uint response) override external {
|
||||||
|
_givenAnyReturn(uintToBytes(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyReturnAddress(address response) override external {
|
||||||
|
_givenAnyReturn(uintToBytes(uint(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyRevert() override external {
|
||||||
|
fallbackMockType = MockType.Revert;
|
||||||
|
fallbackRevertMessage = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyRevertWithMessage(string calldata message) override external {
|
||||||
|
fallbackMockType = MockType.Revert;
|
||||||
|
fallbackRevertMessage = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenAnyRunOutOfGas() override external {
|
||||||
|
fallbackMockType = MockType.OutOfGas;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _givenCalldataReturn(bytes memory call, bytes memory response) private {
|
||||||
|
calldataMockTypes[call] = MockType.Return;
|
||||||
|
calldataExpectations[call] = response;
|
||||||
|
trackCalldataMock(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataReturn(bytes calldata call, bytes calldata response) override external {
|
||||||
|
_givenCalldataReturn(call, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataReturnBool(bytes calldata call, bool response) override external {
|
||||||
|
uint flag = response ? 1 : 0;
|
||||||
|
_givenCalldataReturn(call, uintToBytes(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataReturnUint(bytes calldata call, uint response) override external {
|
||||||
|
_givenCalldataReturn(call, uintToBytes(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataReturnAddress(bytes calldata call, address response) override external {
|
||||||
|
_givenCalldataReturn(call, uintToBytes(uint(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _givenMethodReturn(bytes memory call, bytes memory response) private {
|
||||||
|
bytes4 method = bytesToBytes4(call);
|
||||||
|
methodIdMockTypes[method] = MockType.Return;
|
||||||
|
methodIdExpectations[method] = response;
|
||||||
|
trackMethodIdMock(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodReturn(bytes calldata call, bytes calldata response) override external {
|
||||||
|
_givenMethodReturn(call, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodReturnBool(bytes calldata call, bool response) override external {
|
||||||
|
uint flag = response ? 1 : 0;
|
||||||
|
_givenMethodReturn(call, uintToBytes(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodReturnUint(bytes calldata call, uint response) override external {
|
||||||
|
_givenMethodReturn(call, uintToBytes(response));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodReturnAddress(bytes calldata call, address response) override external {
|
||||||
|
_givenMethodReturn(call, uintToBytes(uint(response)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataRevert(bytes calldata call) override external {
|
||||||
|
calldataMockTypes[call] = MockType.Revert;
|
||||||
|
calldataRevertMessage[call] = "";
|
||||||
|
trackCalldataMock(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodRevert(bytes calldata call) override external {
|
||||||
|
bytes4 method = bytesToBytes4(call);
|
||||||
|
methodIdMockTypes[method] = MockType.Revert;
|
||||||
|
trackMethodIdMock(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataRevertWithMessage(bytes calldata call, string calldata message) override external {
|
||||||
|
calldataMockTypes[call] = MockType.Revert;
|
||||||
|
calldataRevertMessage[call] = message;
|
||||||
|
trackCalldataMock(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodRevertWithMessage(bytes calldata call, string calldata message) override external {
|
||||||
|
bytes4 method = bytesToBytes4(call);
|
||||||
|
methodIdMockTypes[method] = MockType.Revert;
|
||||||
|
methodIdRevertMessages[method] = message;
|
||||||
|
trackMethodIdMock(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenCalldataRunOutOfGas(bytes calldata call) override external {
|
||||||
|
calldataMockTypes[call] = MockType.OutOfGas;
|
||||||
|
trackCalldataMock(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
function givenMethodRunOutOfGas(bytes calldata call) override external {
|
||||||
|
bytes4 method = bytesToBytes4(call);
|
||||||
|
methodIdMockTypes[method] = MockType.OutOfGas;
|
||||||
|
trackMethodIdMock(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
function invocationCount() override external returns (uint) {
|
||||||
|
return invocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
function invocationCountForMethod(bytes calldata call) override external returns (uint) {
|
||||||
|
bytes4 method = bytesToBytes4(call);
|
||||||
|
return methodIdInvocations[keccak256(abi.encodePacked(resetCount, method))];
|
||||||
|
}
|
||||||
|
|
||||||
|
function invocationCountForCalldata(bytes calldata call) override external returns (uint) {
|
||||||
|
return calldataInvocations[keccak256(abi.encodePacked(resetCount, call))];
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset() override external {
|
||||||
|
// Reset all exact calldataMocks
|
||||||
|
bytes memory nextMock = calldataMocks[MOCKS_LIST_START];
|
||||||
|
bytes32 mockHash = keccak256(nextMock);
|
||||||
|
// We cannot compary bytes
|
||||||
|
while(mockHash != MOCKS_LIST_END_HASH) {
|
||||||
|
// Reset all mock maps
|
||||||
|
calldataMockTypes[nextMock] = MockType.Return;
|
||||||
|
calldataExpectations[nextMock] = hex"";
|
||||||
|
calldataRevertMessage[nextMock] = "";
|
||||||
|
// Set next mock to remove
|
||||||
|
nextMock = calldataMocks[mockHash];
|
||||||
|
// Remove from linked list
|
||||||
|
calldataMocks[mockHash] = "";
|
||||||
|
// Update mock hash
|
||||||
|
mockHash = keccak256(nextMock);
|
||||||
|
}
|
||||||
|
// Clear list
|
||||||
|
calldataMocks[MOCKS_LIST_START] = MOCKS_LIST_END;
|
||||||
|
|
||||||
|
// Reset all any calldataMocks
|
||||||
|
bytes4 nextAnyMock = methodIdMocks[SENTINEL_ANY_MOCKS];
|
||||||
|
while(nextAnyMock != SENTINEL_ANY_MOCKS) {
|
||||||
|
bytes4 currentAnyMock = nextAnyMock;
|
||||||
|
methodIdMockTypes[currentAnyMock] = MockType.Return;
|
||||||
|
methodIdExpectations[currentAnyMock] = hex"";
|
||||||
|
methodIdRevertMessages[currentAnyMock] = "";
|
||||||
|
nextAnyMock = methodIdMocks[currentAnyMock];
|
||||||
|
// Remove from linked list
|
||||||
|
methodIdMocks[currentAnyMock] = 0x0;
|
||||||
|
}
|
||||||
|
// Clear list
|
||||||
|
methodIdMocks[SENTINEL_ANY_MOCKS] = SENTINEL_ANY_MOCKS;
|
||||||
|
|
||||||
|
fallbackExpectation = DEFAULT_FALLBACK_VALUE;
|
||||||
|
fallbackMockType = MockType.Return;
|
||||||
|
invocations = 0;
|
||||||
|
resetCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function useAllGas() private {
|
||||||
|
while(true) {
|
||||||
|
bool s;
|
||||||
|
assembly {
|
||||||
|
//expensive call to EC multiply contract
|
||||||
|
s := call(sub(gas(), 2000), 6, 0, 0x0, 0xc0, 0x0, 0x60)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesToBytes4(bytes memory b) private pure returns (bytes4) {
|
||||||
|
bytes4 out;
|
||||||
|
for (uint i = 0; i < 4; i++) {
|
||||||
|
out |= bytes4(b[i] & 0xFF) >> (i * 8);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function uintToBytes(uint256 x) private pure returns (bytes memory b) {
|
||||||
|
b = new bytes(32);
|
||||||
|
assembly { mstore(add(b, 32), x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateInvocationCount(bytes4 methodId, bytes memory originalMsgData) public {
|
||||||
|
require(msg.sender == address(this), "Can only be called from the contract itself");
|
||||||
|
invocations += 1;
|
||||||
|
methodIdInvocations[keccak256(abi.encodePacked(resetCount, methodId))] += 1;
|
||||||
|
calldataInvocations[keccak256(abi.encodePacked(resetCount, originalMsgData))] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fallback () payable external {
|
||||||
|
bytes4 methodId;
|
||||||
|
assembly {
|
||||||
|
methodId := calldataload(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, check exact matching overrides
|
||||||
|
if (calldataMockTypes[msg.data] == MockType.Revert) {
|
||||||
|
revert(calldataRevertMessage[msg.data]);
|
||||||
|
}
|
||||||
|
if (calldataMockTypes[msg.data] == MockType.OutOfGas) {
|
||||||
|
useAllGas();
|
||||||
|
}
|
||||||
|
bytes memory result = calldataExpectations[msg.data];
|
||||||
|
|
||||||
|
// Then check method Id overrides
|
||||||
|
if (result.length == 0) {
|
||||||
|
if (methodIdMockTypes[methodId] == MockType.Revert) {
|
||||||
|
revert(methodIdRevertMessages[methodId]);
|
||||||
|
}
|
||||||
|
if (methodIdMockTypes[methodId] == MockType.OutOfGas) {
|
||||||
|
useAllGas();
|
||||||
|
}
|
||||||
|
result = methodIdExpectations[methodId];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last, use the fallback override
|
||||||
|
if (result.length == 0) {
|
||||||
|
if (fallbackMockType == MockType.Revert) {
|
||||||
|
revert(fallbackRevertMessage);
|
||||||
|
}
|
||||||
|
if (fallbackMockType == MockType.OutOfGas) {
|
||||||
|
useAllGas();
|
||||||
|
}
|
||||||
|
result = fallbackExpectation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record invocation as separate call so we don't rollback in case we are called with STATICCALL
|
||||||
|
(, bytes memory r) = address(this).call.gas(100000)(abi.encodeWithSignature("updateInvocationCount(bytes4,bytes)", methodId, msg.data));
|
||||||
|
assert(r.length == 0);
|
||||||
|
|
||||||
|
assembly {
|
||||||
|
return(add(0x20, result), mload(result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,20 @@
|
||||||
const CurveProtocol = artifacts.require("CurveProtocol");
|
// const CurveProtocol = artifacts.require("CurveProtocol");
|
||||||
const ConnectSBTCCurve = artifacts.require("ConnectSBTCCurve");
|
// const ConnectSBTCCurve = artifacts.require("ConnectSBTCCurve");
|
||||||
|
// const MockContract = artifacts.require("MockContract");
|
||||||
|
// const MockSynthetixStaking = artifacts.require("MockSynthetixStaking");
|
||||||
|
// const ConnectSynthetixStaking = artifacts.require("ConnectSynthetixStaking");
|
||||||
|
|
||||||
const connectorsABI = require("../test/abi/connectors.json");
|
// const connectorsABI = require("../test/abi/connectors.json");
|
||||||
let connectorsAddr = "0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c";
|
// let connectorsAddr = "0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c";
|
||||||
let connectorInstance = new web3.eth.Contract(connectorsABI, connectorsAddr);
|
// let connectorInstance = new web3.eth.Contract(connectorsABI, connectorsAddr);
|
||||||
|
|
||||||
module.exports = async function(deployer) {
|
module.exports = async function(deployer) {
|
||||||
deployer.deploy(CurveProtocol);
|
// deployer.deploy(CurveProtocol);
|
||||||
let connectorLength = await connectorInstance.methods.connectorLength().call();
|
// let connectorLength = await connectorInstance.methods.connectorLength().call();
|
||||||
deployer.deploy(ConnectSBTCCurve, 1, +connectorLength + 1);
|
// deployer.deploy(MockContract).then(function () {
|
||||||
|
// // return deployer.deploy(MockSynthetixStaking, MockContract.address, 1, +connectorLength + 1);
|
||||||
|
// // return deployer.deploy(ConnectSynthetixStaking, MockContract.address);
|
||||||
|
// return deployer.deploy(MockSynthetixStaking, MockContract.address);
|
||||||
|
// });
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
3584
package-lock.json
generated
3584
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -36,11 +36,15 @@
|
||||||
"truffle-verify": "^1.0.8"
|
"truffle-verify": "^1.0.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@nomiclabs/buidler": "^1.3.8",
|
||||||
|
"@nomiclabs/buidler-truffle5": "^1.3.4",
|
||||||
|
"@nomiclabs/buidler-web3": "^1.3.4",
|
||||||
"@openzeppelin/test-helpers": "^0.5.6",
|
"@openzeppelin/test-helpers": "^0.5.6",
|
||||||
"@studydefi/money-legos": "^2.3.5",
|
"@studydefi/money-legos": "^2.3.5",
|
||||||
"ganache-cli": "^6.10.0-beta.2",
|
"ganache-cli": "^6.10.0-beta.2",
|
||||||
"sol-merger": "^2.0.1",
|
"sol-merger": "^2.0.1",
|
||||||
"solidity-coverage": "0.5.11",
|
"solidity-coverage": "0.5.11",
|
||||||
"solium": "1.2.3"
|
"solium": "1.2.3",
|
||||||
|
"web3": "^1.2.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,8 +78,6 @@ contract('ConnectSBTCCurve', async accounts => {
|
||||||
// Send ETH to master
|
// Send ETH to master
|
||||||
await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("5")});
|
await web3.eth.sendTransaction({from: sender, to: masterAddress, value: ether("5")});
|
||||||
|
|
||||||
let connectorID = await connectSBTCCurve.connectorID();
|
|
||||||
|
|
||||||
// Enable the the given connector address
|
// Enable the the given connector address
|
||||||
await connectorInstance.methods.enable(connectSBTCCurve.address).send({from: masterAddress});
|
await connectorInstance.methods.enable(connectSBTCCurve.address).send({from: masterAddress});
|
||||||
// check if the give connector address is enabled.
|
// check if the give connector address is enabled.
|
||||||
|
|
97
test/SynthetixProtocol.js
Normal file
97
test/SynthetixProtocol.js
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
const {
|
||||||
|
BN, // Big Number support
|
||||||
|
expectEvent, // Assertions for emitted events
|
||||||
|
expectRevert, // Assertions for transactions that should fail
|
||||||
|
balance,
|
||||||
|
ether
|
||||||
|
} = require('@openzeppelin/test-helpers');
|
||||||
|
|
||||||
|
const MockContract = artifacts.require("MockContract");
|
||||||
|
const MockSynthetixStaking = artifacts.require('MockSynthetixStaking');
|
||||||
|
const MockInstaMapping = artifacts.require('MockInstaMapping');
|
||||||
|
const erc20ABI = require("./abi/erc20.js");
|
||||||
|
const synthetixStaking = require("./abi/synthetixStaking.json");
|
||||||
|
|
||||||
|
contract('ConnectSynthetixStaking', async accounts => {
|
||||||
|
const [sender, receiver] = accounts;
|
||||||
|
let mock, mockSynthetixStaking, stakingContract, token;
|
||||||
|
let instaMapping;
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
mock = await MockContract.new();
|
||||||
|
mockInstaMapping = await MockInstaMapping.new();
|
||||||
|
mockSynthetixStaking = await MockSynthetixStaking.new(mock.address, mockInstaMapping.address);
|
||||||
|
stakingContract = new web3.eth.Contract(synthetixStaking, mock.address);
|
||||||
|
token = new web3.eth.Contract(erc20ABI, mock.address);
|
||||||
|
mockInstaMapping.addStakingMapping('snx', mock.address, mock.address);
|
||||||
|
|
||||||
|
// mocking balanceOf
|
||||||
|
let balanceOf = await token.methods.balanceOf(mockSynthetixStaking.address).encodeABI();
|
||||||
|
await mock.givenMethodReturnUint(balanceOf, 10000000);
|
||||||
|
|
||||||
|
// mocking approve
|
||||||
|
let approve = await token.methods.approve(mockSynthetixStaking.address, 10000000).encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(approve, "true");
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can deposit', async function() {
|
||||||
|
// mocking stake
|
||||||
|
let stake = await stakingContract.methods.stake(10000000).encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(stake, "true");
|
||||||
|
|
||||||
|
const tx = await mockSynthetixStaking.deposit(
|
||||||
|
"snx",
|
||||||
|
10000000,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
expectEvent(tx, "LogDeposit");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can withdraw', async function() {
|
||||||
|
// mocking withdraw
|
||||||
|
let withdraw = await stakingContract.methods.withdraw(10000000).encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(withdraw, "true");
|
||||||
|
// mocking getReward
|
||||||
|
let reward = await stakingContract.methods.getReward().encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(reward, "true");
|
||||||
|
|
||||||
|
const tx = await mockSynthetixStaking.withdraw(
|
||||||
|
"snx",
|
||||||
|
10000000,
|
||||||
|
0,
|
||||||
|
111,
|
||||||
|
112
|
||||||
|
)
|
||||||
|
expectEvent(tx, "LogWithdraw");
|
||||||
|
expectEvent(tx, "LogClaimedReward");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can claim reward', async function() {
|
||||||
|
// mocking getReward
|
||||||
|
let reward = await stakingContract.methods.getReward().encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(reward, "true");
|
||||||
|
const tx = await mockSynthetixStaking.claimReward(
|
||||||
|
"snx",
|
||||||
|
112
|
||||||
|
)
|
||||||
|
expectEvent(tx, "LogClaimedReward");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('cannot deposit if pool removed', async function() {
|
||||||
|
mockInstaMapping.removeStakingMapping('snx', mock.address);
|
||||||
|
// mocking stake
|
||||||
|
let stake = await stakingContract.methods.stake(10000000).encodeABI();
|
||||||
|
await mock.givenMethodReturnBool(stake, "true");
|
||||||
|
|
||||||
|
const tx = mockSynthetixStaking.deposit(
|
||||||
|
"snx",
|
||||||
|
10000000,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
)
|
||||||
|
expectRevert(tx, "Wrong Staking Name");
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
1
test/abi/crvRenWSBTC.json
Normal file
1
test/abi/crvRenWSBTC.json
Normal file
|
@ -0,0 +1 @@
|
||||||
|
[{"name":"Transfer","inputs":[{"type":"address","name":"_from","indexed":true},{"type":"address","name":"_to","indexed":true},{"type":"uint256","name":"_value","indexed":false}],"anonymous":false,"type":"event"},{"name":"Approval","inputs":[{"type":"address","name":"_owner","indexed":true},{"type":"address","name":"_spender","indexed":true},{"type":"uint256","name":"_value","indexed":false}],"anonymous":false,"type":"event"},{"outputs":[],"inputs":[{"type":"string","name":"_name"},{"type":"string","name":"_symbol"},{"type":"uint256","name":"_decimals"},{"type":"uint256","name":"_supply"}],"constant":false,"payable":false,"type":"constructor"},{"name":"set_minter","outputs":[],"inputs":[{"type":"address","name":"_minter"}],"constant":false,"payable":false,"type":"function","gas":36247},{"name":"totalSupply","outputs":[{"type":"uint256","name":"out"}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":1181},{"name":"allowance","outputs":[{"type":"uint256","name":"out"}],"inputs":[{"type":"address","name":"_owner"},{"type":"address","name":"_spender"}],"constant":true,"payable":false,"type":"function","gas":1519},{"name":"transfer","outputs":[{"type":"bool","name":"out"}],"inputs":[{"type":"address","name":"_to"},{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":74802},{"name":"transferFrom","outputs":[{"type":"bool","name":"out"}],"inputs":[{"type":"address","name":"_from"},{"type":"address","name":"_to"},{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":111953},{"name":"approve","outputs":[{"type":"bool","name":"out"}],"inputs":[{"type":"address","name":"_spender"},{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":39012},{"name":"mint","outputs":[],"inputs":[{"type":"address","name":"_to"},{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":75733},{"name":"burn","outputs":[],"inputs":[{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":76623},{"name":"burnFrom","outputs":[],"inputs":[{"type":"address","name":"_to"},{"type":"uint256","name":"_value"}],"constant":false,"payable":false,"type":"function","gas":76696},{"name":"name","outputs":[{"type":"string","name":"out"}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":7853},{"name":"symbol","outputs":[{"type":"string","name":"out"}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":6906},{"name":"decimals","outputs":[{"type":"uint256","name":"out"}],"inputs":[],"constant":true,"payable":false,"type":"function","gas":1511},{"name":"balanceOf","outputs":[{"type":"uint256","name":"out"}],"inputs":[{"type":"address","name":"arg0"}],"constant":true,"payable":false,"type":"function","gas":1695}]
|
1
test/abi/synthetixStaking.json
Normal file
1
test/abi/synthetixStaking.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,40 +1,10 @@
|
||||||
/**
|
|
||||||
* Use this file to configure your truffle project. It's seeded with some
|
|
||||||
* common settings for different networks and features like migrations,
|
|
||||||
* compilation and testing. Uncomment the ones you need or modify
|
|
||||||
* them to suit your project as necessary.
|
|
||||||
*
|
|
||||||
* More information about configuration can be found at:
|
|
||||||
*
|
|
||||||
* truffleframework.com/docs/advanced/configuration
|
|
||||||
*
|
|
||||||
* To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider)
|
|
||||||
* to sign your transactions before they're sent to a remote public node. Infura accounts
|
|
||||||
* are available for free at: infura.io/register.
|
|
||||||
*
|
|
||||||
* You'll also need a mnemonic - the twelve word phrase the wallet uses to generate
|
|
||||||
* public/private key pairs. If you're publishing your code to GitHub make sure you load this
|
|
||||||
* phrase from a file you've .gitignored so it doesn't accidentally become public.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
const HDWalletProvider = require('truffle-hdwallet-provider');
|
const HDWalletProvider = require('truffle-hdwallet-provider');
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv');
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
const infuraKey = process.env.infura_key;
|
const infuraKey = process.env.infura_key;
|
||||||
//
|
|
||||||
const mnemonic = process.env.mnemonic_key;
|
const mnemonic = process.env.mnemonic_key;
|
||||||
module.exports = {
|
module.exports = {
|
||||||
/**
|
|
||||||
* Networks define how you connect to your ethereum client and let you set the
|
|
||||||
* defaults web3 uses to send transactions. If you don't specify one truffle
|
|
||||||
* will spin up a development blockchain for you on port 9545 when you
|
|
||||||
* run `develop` or `test`. You can ask a truffle command to use a specific
|
|
||||||
* network from the command line, e.g
|
|
||||||
*
|
|
||||||
* $ truffle test --network <network-name>
|
|
||||||
*/
|
|
||||||
plugins: [
|
plugins: [
|
||||||
'truffle-plugin-verify',
|
'truffle-plugin-verify',
|
||||||
],
|
],
|
||||||
|
@ -43,36 +13,18 @@ module.exports = {
|
||||||
},
|
},
|
||||||
|
|
||||||
networks: {
|
networks: {
|
||||||
// Useful for testing. The `development` name is special - truffle uses it by default
|
|
||||||
// if it's defined here and no other network is specified at the command line.
|
|
||||||
// You should run a client (like ganache-cli, geth or parity) in a separate terminal
|
|
||||||
// tab if you use this network and you must also set the `host`, `port` and `network_id`
|
|
||||||
// options below to some value.
|
|
||||||
//
|
|
||||||
development: {
|
development: {
|
||||||
host: "127.0.0.1", // Localhost (default: none)
|
host: "127.0.0.1",
|
||||||
port: 8545, // Standard Ethereum port (default: none)
|
port: 8545,
|
||||||
network_id: "*", // Any network (default: none)
|
network_id: "*",
|
||||||
},
|
},
|
||||||
// Tenderly Proxy
|
|
||||||
proxy: {
|
proxy: {
|
||||||
host: "127.0.0.1", // Localhost (default: none)
|
host: "127.0.0.1",
|
||||||
port: 9545, // Standard Ethereum port (default: none)
|
port: 9545,
|
||||||
network_id: "*", // Any network (default: none)
|
network_id: "*",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Another network with more advanced options...
|
|
||||||
// advanced: {
|
|
||||||
// port: 8777, // Custom port
|
|
||||||
// network_id: 1342, // Custom network
|
|
||||||
// gas: 8500000, // Gas sent with each transaction (default: ~6700000)
|
|
||||||
// gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei)
|
|
||||||
// from: <address>, // Account to send txs from (default: accounts[0])
|
|
||||||
// websockets: true // Enable EventEmitter interface for web3 (default: false)
|
|
||||||
// },
|
|
||||||
|
|
||||||
// Useful for deploying to a public network.
|
|
||||||
// NB: It's important to wrap the provider as a function.
|
|
||||||
live: {
|
live: {
|
||||||
provider: () => new HDWalletProvider(mnemonic, `https://mainnet.infura.io/v3/${infuraKey}`),
|
provider: () => new HDWalletProvider(mnemonic, `https://mainnet.infura.io/v3/${infuraKey}`),
|
||||||
network_id: 1,
|
network_id: 1,
|
||||||
|
@ -97,13 +49,6 @@ module.exports = {
|
||||||
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
|
timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50)
|
||||||
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
|
skipDryRun: true // Skip dry run before migrations? (default: false for public nets )
|
||||||
},
|
},
|
||||||
|
|
||||||
// Useful for private networks
|
|
||||||
// private: {
|
|
||||||
// provider: () => new HDWalletProvider(mnemonic, `https://network.io`),
|
|
||||||
// network_id: 2111, // This network is yours, in the cloud.
|
|
||||||
// production: true // Treats this network as if it was a public net. (default: false)
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Set default mocha options here, use special reporters etc.
|
// Set default mocha options here, use special reporters etc.
|
||||||
|
@ -114,15 +59,13 @@ module.exports = {
|
||||||
// Configure your compilers
|
// Configure your compilers
|
||||||
compilers: {
|
compilers: {
|
||||||
solc: {
|
solc: {
|
||||||
version: "v0.6.2", // Fetch exact version from solc-bin (default: truffle's version)
|
version: "v0.6.2",
|
||||||
// docker: true, // Use "0.5.1" you've installed locally with docker (default: false)
|
settings: {
|
||||||
// settings: { // See the solidity docs for advice about optimization and evmVersion
|
optimizer: {
|
||||||
// optimizer: {
|
enabled: true,
|
||||||
enabled: false,
|
},
|
||||||
// runs: 200
|
|
||||||
// },
|
|
||||||
// evmVersion: "istanbul"
|
// evmVersion: "istanbul"
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user