Skip to content

Commit

Permalink
Versioning contracts (#383)
Browse files Browse the repository at this point in the history
Create 'IPeanalizer' interface & add 'versionX' fields to all GSN interfaces
  • Loading branch information
forshtat authored May 27, 2020
1 parent cffdab4 commit fabb7f0
Show file tree
Hide file tree
Showing 24 changed files with 105 additions and 30 deletions.
9 changes: 9 additions & 0 deletions .idea/dictionaries/alexf.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/BaseRelayRecipient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import "./interfaces/IRelayRecipient.sol";
* A base contract to be inherited by any contract that want to receive relayed transactions
* A subclass must use "_msgSender()" instead of "msg.sender"
*/
contract BaseRelayRecipient is IRelayRecipient {
abstract contract BaseRelayRecipient is IRelayRecipient {

/// the TrustedForwarder singleton we accept calls from.
// we trust it to verify the caller's signature, and pass the caller's address as last 20 bytes
Expand Down
24 changes: 12 additions & 12 deletions contracts/Penalizer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,13 @@ import "@openzeppelin/contracts/cryptography/ECDSA.sol";
import "./utils/RLPReader.sol";
import "./utils/GsnUtils.sol";
import "./interfaces/IRelayHub.sol";
import "./interfaces/IPenalizer.sol";

contract Penalizer {
using ECDSA for bytes32;
contract Penalizer is IPenalizer{

struct Transaction {
uint256 nonce;
uint256 gasPrice;
uint256 gasLimit;
address to;
uint256 value;
bytes data;
}
string public override versionPenalizer = "2.0.0-alpha.1+opengsn.penalizer.ipenalizer";

using ECDSA for bytes32;

function decodeTransaction(bytes memory rawTransaction) private pure returns (Transaction memory transaction) {
(transaction.nonce,
Expand All @@ -37,7 +32,9 @@ contract Penalizer {
bytes memory unsignedTx2,
bytes memory signature2,
IRelayHub hub
) public
)
public
override
{
// Can be called by anyone.
// If a relay attacked the system by signing multiple transactions with the same nonce
Expand Down Expand Up @@ -79,7 +76,10 @@ contract Penalizer {
bytes memory unsignedTx,
bytes memory signature,
IRelayHub hub
) public {
)
public
override
{
Transaction memory decodedTx = decodeTransaction(unsignedTx);
if (decodedTx.to == address(hub)) {
bytes4 selector = GsnUtils.getMethodSig(decodedTx.data);
Expand Down
11 changes: 2 additions & 9 deletions contracts/RelayHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import "./Penalizer.sol";

contract RelayHub is IRelayHub {

string constant public COMMIT_ID = "$Id$";
string public override versionHub = "2.0.0-alpha.1+opengsn.hub.irelayhub";

// Minimum stake a relay can have. An attack to the network will never cost less than half this value.
uint256 constant private MINIMUM_STAKE = 1 ether;
Expand All @@ -42,7 +42,7 @@ contract RelayHub is IRelayHub {
*/

// Gas cost of all relayCall() instructions after actual 'calculateCharge()'
uint256 constant private GAS_OVERHEAD = 36834;
uint256 constant private GAS_OVERHEAD = 36800;

function getHubOverhead() external override view returns (uint256) {
return GAS_OVERHEAD;
Expand All @@ -63,13 +63,6 @@ contract RelayHub is IRelayHub {

mapping(address => uint256) private balances;

string public version = "1.0.0";
// TODO: remove with 0.6 solc
function getVersion() external override view returns (string memory) {
return version;
}


EIP712Sig public eip712sig;
StakeManager public stakeManager;
Penalizer public penalizer;
Expand Down
2 changes: 2 additions & 0 deletions contracts/StakeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "./interfaces/IStakeManager.sol";

contract StakeManager is IStakeManager {

string public override versionSM = "2.0.0-alpha.1+opengsn.stakemanager.istakemanager";

/// maps relay managers to their stakes
mapping(address => StakeInfo) public stakes;
function getStakeInfo(address relayManager) external override view returns (StakeInfo memory stakeInfo) {
Expand Down
6 changes: 6 additions & 0 deletions contracts/TrustedBatchForwarder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import "./utils/GsnUtils.sol";
*/
contract TrustedBatchForwarder is TrustedForwarder, BaseRelayRecipient {

function versionForwarder() external view override returns (string memory){
return "2.0.0-alpha.1+opengsn.batched.iforwarder";
}

string public override versionRecipient = "2.0.0-alpha.1+opengsn.batched.irelayrecipient";

constructor() public {
//needed for sendBatch
trustedForwarder = address(this);
Expand Down
4 changes: 4 additions & 0 deletions contracts/TrustedForwarder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import "./interfaces/ITrustedForwarder.sol";

contract TrustedForwarder is ITrustedForwarder {

function versionForwarder() external view virtual override returns (string memory){
return "2.0.0-alpha.1+opengsn.forwarder.iforwarder";
}

EIP712Sig private eip712sig;

// Nonces of senders, used to prevent replay attacks
Expand Down
1 change: 1 addition & 0 deletions contracts/interfaces/IPaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,5 @@ interface IPaymaster {
GSNTypes.GasData calldata gasData
) external;

function versionPaymaster() external view returns (string memory);
}
32 changes: 32 additions & 0 deletions contracts/interfaces/IPenalizer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier:MIT
pragma solidity ^0.6.2;

import "./IRelayHub.sol";

interface IPenalizer {

struct Transaction {
uint256 nonce;
uint256 gasPrice;
uint256 gasLimit;
address to;
uint256 value;
bytes data;
}

function penalizeRepeatedNonce(
bytes calldata unsignedTx1,
bytes calldata signature1,
bytes calldata unsignedTx2,
bytes calldata signature2,
IRelayHub hub
) external;

function penalizeIllegalTransaction(
bytes calldata unsignedTx,
bytes calldata signature,
IRelayHub hub
) external;

function versionPenalizer() external view returns (string memory);
}
2 changes: 1 addition & 1 deletion contracts/interfaces/IRelayHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ interface IRelayHub {
/// charged for 1.4 times the spent amount.
function calculateCharge(uint256 gasUsed, GSNTypes.GasData calldata gasData) external view returns (uint256);

function getVersion() external view returns (string memory);
function versionHub() external view returns (string memory);

}

2 changes: 2 additions & 0 deletions contracts/interfaces/IRelayRecipient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ abstract contract IRelayRecipient {
* should be used in the contract anywhere instead of msg.sender
*/
function _msgSender() internal virtual view returns (address payable);

function versionRecipient() external virtual view returns (string memory);
}
2 changes: 2 additions & 0 deletions contracts/interfaces/IStakeManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,6 @@ interface IStakeManager {
function penalizeRelayManager(address relayManager, address payable beneficiary, uint256 amount) external;

function getStakeInfo(address relayManager) external view returns (StakeInfo memory stakeInfo);

function versionSM() external view returns (string memory);
}
2 changes: 2 additions & 0 deletions contracts/interfaces/ITrustedForwarder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ interface ITrustedForwarder {
function verifyAndCall(GSNTypes.RelayRequest calldata req, bytes calldata sig) external;

function getNonce(address from) external view returns (uint256);

function versionForwarder() external view returns (string memory);
}
1 change: 1 addition & 0 deletions contracts/paymaster/TokenPaymaster.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import "./IUniswap.sol";
* - postRelayedCall - refund the caller for the unused gas
*/
contract TokenPaymaster is BasePaymaster {
string public override versionPaymaster = "2.0.0-alpha.1+opengsn.token.ipaymaster";

IUniswap public uniswap;
IERC20 public token;
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/PayableWithEmit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import "../0x/LibBytesV06.sol";
// it should work)
contract PayableWithEmit is BaseRelayRecipient {

string public override versionRecipient = "2.0.0-alpha.1+opengsn.payablewithemit.irelayrecipient";

event Received(address sender, uint value, uint gasleft);

receive () external payable {
Expand Down
4 changes: 4 additions & 0 deletions contracts/test/TestPaymasterEverythingAccepted.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import "../BasePaymaster.sol";

contract TestPaymasterEverythingAccepted is BasePaymaster {

function versionPaymaster() external view override virtual returns (string memory){
return "2.0.0-alpha.1+opengsn.test_pea.ipaymaster";
}

event SampleRecipientPreCall();
event SampleRecipientPostCall(bool success, uint actualCharge, bytes32 preRetVal);

Expand Down
2 changes: 2 additions & 0 deletions contracts/test/TestPaymasterVariableGasLimits.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import "./TestPaymasterEverythingAccepted.sol";

contract TestPaymasterVariableGasLimits is TestPaymasterEverythingAccepted {

string public override versionPaymaster = "2.0.0-alpha.1+opengsn.test-vgl.ipaymaster";

event SampleRecipientPreCallWithValues(
uint256 gasleft,
uint256 arcGasleft,
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/TestProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "../BaseRelayRecipient.sol";

contract TestProxy is BaseRelayRecipient, Ownable {

string public override versionRecipient = "2.0.0-alpha.1+opengsn.testproxy.irelayrecipient";

constructor(address forwarder) public {
trustedForwarder = forwarder;
}
Expand Down
2 changes: 2 additions & 0 deletions contracts/test/TestRecipient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import "../interfaces/IKnowForwarderAddress.sol";

contract TestRecipient is BaseRelayRecipient, IKnowForwarderAddress {

string public override versionRecipient = "2.0.0-alpha.1+opengsn.test.irelayrecipient";

constructor() public {
//should be a singleton, since Paymaster should (eventually) trust it.
trustedForwarder = address(new TrustedForwarder());
Expand Down
2 changes: 1 addition & 1 deletion src/cli/CommandsLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export default class CommandsLogic {
async deployGsnContracts (from: Address, gasPrice?: string, paymaster?: any): Promise<DeploymentResult> {
const options = {
from,
gas: 1e6,
gas: 3e6,
gasPrice: gasPrice ?? (1e9).toString()
}

Expand Down
6 changes: 6 additions & 0 deletions src/common/VersionsManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// TODO: this is just a stub of what would be fully-featured version manager
export default class VersionsManager {
isHubVersionSupported (version: string): boolean {
return version === '2.0.0-alpha.1+opengsn.hub.irelayhub'
}
}
7 changes: 5 additions & 2 deletions src/relayserver/RelayServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { TransactionReceipt } from 'web3-core'
import { toBN, toHex } from 'web3-utils'
import { configureGSN } from '../relayclient/GSNConfigurator'
import { defaultEnvironment } from '../relayclient/types/Environments'
import VersionsManager from '../common/VersionsManager'

abiDecoder.addABI(RelayHubABI)
abiDecoder.addABI(PayMasterABI)
Expand Down Expand Up @@ -135,6 +136,7 @@ export class RelayServer extends EventEmitter {
private readonly web3provider: provider
readonly keyManager: KeyManager
private readonly contractInteractor: ContractInteractor
private readonly versionManager: VersionsManager
readonly hubAddress: PrefixedHexString
readonly baseRelayFee: number
readonly pctRelayFee: number
Expand All @@ -147,6 +149,7 @@ export class RelayServer extends EventEmitter {

constructor (params: RelayServerParams) {
super()
this.versionManager = new VersionsManager()
this.txStoreManager = params.txStoreManager
this.web3provider = params.web3provider
this.keyManager = params.keyManager
Expand Down Expand Up @@ -407,8 +410,8 @@ export class RelayServer extends EventEmitter {
} else {
debug('code length', code.length)
}
const version = await this.relayHubContract.getVersion().catch(_ => 'no getVersion() method')
if (version !== '1.0.0') {
const version = await this.relayHubContract.versionHub().catch(_ => 'no getVersion() method')
if (!this.versionManager.isHubVersionSupported(version)) {
this.fatal(`Not a valid RelayHub at ${relayHubAddress}: version: ${version}`)
}
const stakeManagerAddress = await this.relayHubContract.getStakeManager()
Expand Down
4 changes: 2 additions & 2 deletions test/RelayHub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ contract('RelayHub', function ([_, relayOwner, relayManager, relayWorker, sender
})

it('should retrieve version number', async function () {
const version = await relayHubInstance.version()
assert.equal(version, '1.0.0')
const version = await relayHubInstance.versionHub()
assert.match(version, /2\.\d*\.\d*-?.*\+opengsn\.hub\.irelayhub/)
})
describe.skip('balances', function () {
async function testDeposit (sender: string, paymaster: string, amount: BN): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions test/RelayHubGasCalculations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ contract('RelayHub gas calculations', function ([_, relayOwner, relayWorker, rel
const gasLimit = new BN('1000000')
const senderNonce = new BN('0')
const magicNumbers = {
arc: 844,
pre: 1508,
arc: 867,
pre: 1486,
post: 1583
}

Expand Down

0 comments on commit fabb7f0

Please sign in to comment.