Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@drortirosh @shahafn @alex-forshtat-tbk @nventuro
83 lines (69 sloc) 3.4 KB
pragma solidity ^0.5.5;
// Contract that implements the relay recipient protocol. Inherited by Gatekeeper, or any other relay recipient.
//
// The recipient contract is responsible to:
// * pass a trusted IRelayHub singleton to the constructor.
// * Implement acceptRelayedCall, which acts as a whitelist/blacklist of senders. It is advised that the recipient's owner will be able to update that list to remove abusers.
// * In every function that cares about the sender, use "address sender = getSender()" instead of msg.sender. It'll return msg.sender for non-relayed transactions, or the real sender in case of relayed transactions.
import "./IRelayRecipient.sol";
import "./IRelayHub.sol";
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
contract RelayRecipient is IRelayRecipient {
IRelayHub private relayHub; // The IRelayHub singleton which is allowed to call us
function getHubAddr() public view returns (address) {
return address(relayHub);
}
/**
* Initialize the RelayHub of this contract.
* Must be called at least once (e.g. from the constructor), so that the contract can accept relayed calls.
* For ownable contracts, there should be a method to update the RelayHub, in case a new hub is deployed (since
* the RelayHub itself is not upgradeable)
* Otherwise, the contract might be locked on a dead hub, with no relays.
*/
function setRelayHub(IRelayHub _rhub) internal {
relayHub = _rhub;
//attempt a read method, just to validate the relay is a valid RelayHub contract.
getRecipientBalance();
}
function getRelayHub() internal view returns (IRelayHub) {
return relayHub;
}
/**
* return the balance of this contract.
* Note that this method will revert on configuration error (invalid relay address)
*/
function getRecipientBalance() public view returns (uint) {
return getRelayHub().balanceOf(address(this));
}
function getSenderFromData(address origSender, bytes memory msgData) public view returns (address) {
address sender = origSender;
if (origSender == getHubAddr()) {
// At this point we know that the sender is a trusted IRelayHub, so we trust that the last bytes of msg.data are the verified sender address.
// extract sender address from the end of msg.data
sender = LibBytes.readAddress(msgData, msgData.length - 20);
}
return sender;
}
/**
* return the sender of this call.
* if the call came through the valid RelayHub, return the original sender.
* otherwise, return `msg.sender`
* should be used in the contract anywhere instead of msg.sender
*/
function getSender() public view returns (address) {
return getSenderFromData(msg.sender, msg.data);
}
function getMessageData() public view returns (bytes memory) {
bytes memory origMsgData = msg.data;
if (msg.sender == getHubAddr()) {
// At this point we know that the sender is a trusted IRelayHub, so we trust that the last bytes of msg.data are the verified sender address.
// extract original message data from the start of msg.data
origMsgData = new bytes(msg.data.length - 20);
for (uint256 i = 0; i < origMsgData.length; i++)
{
origMsgData[i] = msg.data[i];
}
}
return origMsgData;
}
}
You can’t perform that action at this time.