-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
Showing
1 changed file
with
60 additions
and
0 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,60 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.6.10; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v3.0.0/contracts/cryptography/ECDSA.sol"; | ||
|
||
contract MultiSigWallet { | ||
using ECDSA for bytes32; | ||
|
||
address[2] public owners; | ||
mapping(bytes32 => bool) public executed; | ||
|
||
constructor(address[2] memory _owners) public payable { | ||
owners = _owners; | ||
} | ||
|
||
function deposit() external payable {} | ||
|
||
function transfer( | ||
address _to, | ||
uint _amount, | ||
uint _nonce, | ||
bytes[2] memory _sigs | ||
) external { | ||
bytes32 txHash = getTxHash(_to, _amount, _nonce); | ||
require(!executed[txHash], "tx executed"); | ||
require(_checkSigs(_sigs, txHash), "invalid sig"); | ||
|
||
executed[txHash] = true; | ||
|
||
(bool sent, ) = _to.call{value: _amount}(""); | ||
require(sent, "Failed to send Ether"); | ||
} | ||
|
||
function getTxHash( | ||
address _to, | ||
uint _amount, | ||
uint _nonce | ||
) public view returns (bytes32) { | ||
return keccak256(abi.encodePacked(address(this), _to, _amount, _nonce)); | ||
} | ||
|
||
function _checkSigs( | ||
bytes[2] memory _sigs, | ||
bytes32 _txHash | ||
) private view returns (bool) { | ||
bytes32 ethSignedHash = _txHash.toEthSignedMessageHash(); | ||
|
||
for (uint i = 0; i < _sigs.length; i++) { | ||
address signer = ethSignedHash.recover(_sigs[i]); | ||
bool valid = signer == owners[i]; | ||
|
||
if (!valid) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
} |