This repository has been archived by the owner on Dec 27, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
1,303 additions
and
159 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
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,106 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.7.1; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "./interfaces/IERC20.sol"; | ||
import "./lib/LibAsset.sol"; | ||
import "./lib/LibUtils.sol"; | ||
import "./EmergencyWithdrawable.sol"; | ||
|
||
|
||
contract AssetTransfer is EmergencyWithdrawable { | ||
|
||
// TODO: These are ad hoc values. Confirm or find more suitable ones. | ||
uint256 private constant ETHER_TRANSFER_GAS_LIMIT = 10000; | ||
uint256 private constant ERC20_TRANSFER_GAS_LIMIT = 100000; | ||
uint256 private constant ERC20_BALANCE_GAS_LIMIT = 5000; | ||
|
||
mapping(address => uint256) private _totalTransferred; | ||
|
||
modifier onlySelf() { | ||
require( | ||
msg.sender == address(this), | ||
"AssetTransfer: Can only be called from this contract" | ||
); | ||
_; | ||
} | ||
|
||
function safelyTransferEther(address payable recipient, uint256 maxAmount) | ||
private | ||
returns (bool, uint256) | ||
{ | ||
uint256 balance = address(this).balance; | ||
uint256 amount = LibUtils.min(maxAmount, balance); | ||
(bool success, ) = recipient.call{gas: ETHER_TRANSFER_GAS_LIMIT, value: amount}(""); | ||
return (success, success ? amount : 0); | ||
} | ||
|
||
function safelyTransferERC20(address assetId, address recipient, uint256 maxAmount) | ||
private | ||
returns (bool, uint256) | ||
{ | ||
(bool success, bytes memory encodedReturnValue) = address(this).call{gas: ERC20_BALANCE_GAS_LIMIT}( | ||
abi.encodeWithSignature("_getOwnERC20Balance(address)", assetId) | ||
); | ||
if (!success) { return (false, 0); } | ||
|
||
uint256 balance = abi.decode(encodedReturnValue, (uint256)); | ||
uint256 amount = LibUtils.min(maxAmount, balance); | ||
(success, ) = address(this).call{gas: ERC20_TRANSFER_GAS_LIMIT}( | ||
abi.encodeWithSignature("_transferERC20(address,address,uint256)", assetId, recipient, amount) | ||
); | ||
return (success, success ? amount : 0); | ||
} | ||
|
||
function safelyTransfer(address assetId, address payable recipient, uint256 maxAmount) | ||
private | ||
returns (bool, uint256) | ||
{ | ||
return LibAsset.isEther(assetId) ? | ||
safelyTransferEther(recipient, maxAmount) : | ||
safelyTransferERC20(assetId, recipient, maxAmount); | ||
|
||
} | ||
|
||
function _getOwnERC20Balance(address assetId) | ||
external | ||
onlySelf | ||
view | ||
returns (uint256) | ||
{ | ||
return IERC20(assetId).balanceOf(address(this)); | ||
} | ||
|
||
function _transferERC20(address assetId, address recipient, uint256 amount) | ||
external | ||
onlySelf | ||
returns (bool) | ||
{ | ||
return LibAsset.transferERC20(assetId, recipient, amount); | ||
} | ||
|
||
function totalTransferred(address assetId) public view returns (uint256) { | ||
return _totalTransferred[assetId]; | ||
} | ||
|
||
function registerTransfer(address assetId, uint256 amount) internal { | ||
_totalTransferred[assetId] += amount; | ||
} | ||
|
||
function transferAsset(address assetId, address payable recipient, uint256 maxAmount) | ||
internal | ||
returns (bool) | ||
{ | ||
(bool success, uint256 amount) = safelyTransfer(assetId, recipient, maxAmount); | ||
|
||
if (success) { | ||
registerTransfer(assetId, amount); | ||
} else { | ||
addToEmergencyWithdrawableAmount(assetId, recipient, maxAmount); | ||
registerTransfer(assetId, maxAmount); | ||
} | ||
|
||
return success; | ||
} | ||
|
||
} |
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,38 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.7.1; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "./interfaces/ICMCAccountant.sol"; | ||
import "./interfaces/Types.sol"; | ||
import "./AssetTransfer.sol"; | ||
import "./CMCDeposit.sol"; | ||
import "./CMCWithdraw.sol"; | ||
|
||
|
||
contract CMCAccountant is | ||
AssetTransfer, | ||
CMCDeposit, | ||
CMCWithdraw, | ||
ICMCAccountant | ||
{ | ||
|
||
function transferBalance(address assetId, Balance memory balance) | ||
internal | ||
{ | ||
address payable recipient; | ||
uint256 amount; | ||
|
||
recipient = balance.to[0]; | ||
amount = balance.amount[0]; | ||
if (amount != 0) { | ||
transferAsset(assetId, recipient, amount); | ||
} | ||
|
||
recipient = balance.to[1]; | ||
amount = balance.amount[1]; | ||
if (amount != 0) { | ||
transferAsset(assetId, recipient, amount); | ||
} | ||
} | ||
|
||
} |
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
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
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 |
---|---|---|
|
@@ -3,55 +3,45 @@ pragma solidity ^0.7.1; | |
pragma experimental ABIEncoderV2; | ||
|
||
import "./interfaces/ICMCDeposit.sol"; | ||
import "./interfaces/Types.sol"; | ||
import "./interfaces/IERC20.sol"; | ||
import "./CMCCore.sol"; | ||
import "./AssetTransfer.sol"; | ||
import "./lib/LibAsset.sol"; | ||
|
||
|
||
/// @title Vector Channel | ||
/// @author Arjun Bhuptani <[email protected]> | ||
/// @notice | ||
/// (a) A proxy to this contract is deployed per-channel using the ChannelFactory.sol contract | ||
/// (b) Executes transactions dispute logic on a hardcoded channel factory | ||
/// (c) Supports executing arbitrary CALLs when called w/ commitment that has 2 signatures | ||
contract CMCDeposit is CMCCore, AssetTransfer, ICMCDeposit { | ||
|
||
contract CMCDeposit is CMCCore, ICMCDeposit { | ||
mapping(address => uint256) private _totalDepositedA; | ||
|
||
receive() external payable onlyOnProxy {} | ||
|
||
function getBalance(address assetId) public override view returns (uint256) { | ||
return assetId == address(0) | ||
? address(this).balance | ||
: IERC20(assetId).balanceOf(address(this)); | ||
} | ||
|
||
function totalDepositedA(address assetId) public override view returns (uint256) { | ||
return _totalDepositedA[assetId]; | ||
} | ||
|
||
// Calculated using invariant onchain properties. Note we DONT use safemath here | ||
function totalDepositedB(address assetId) public override view returns (uint256) { | ||
return getBalance(assetId) + _totalWithdrawn[assetId] - _totalDepositedA[assetId]; | ||
return LibAsset.getOwnBalance(assetId) + totalTransferred(assetId) - _totalDepositedA[assetId]; | ||
} | ||
|
||
function depositA( | ||
address assetId, | ||
uint256 amount | ||
) | ||
public | ||
override | ||
external | ||
payable | ||
override | ||
onlyOnProxy | ||
{ | ||
if (assetId == address(0)) { | ||
if (LibAsset.isEther(assetId)) { | ||
require( | ||
msg.value == amount, | ||
"msg.value does not match the provided amount" | ||
"CMCDeposit: msg.value does not match the provided amount" | ||
); | ||
} else { | ||
require( | ||
IERC20(assetId).transferFrom(msg.sender, address(this), amount), | ||
"ERC20: transferFrom failed" | ||
"CMCDeposit: ERC20 transferFrom failed" | ||
); | ||
} | ||
// NOTE: explicitly do NOT use safemath here | ||
|
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
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
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.