123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- const { BN, expectRevert } = require('@openzeppelin/test-helpers');
- const ethereumjsUtil = require('ethereumjs-util');
- const { expect } = require('chai');
- const DummyImplementation = artifacts.require('DummyImplementation');
- const IMPLEMENTATION_LABEL = 'eip1967.proxy.implementation';
- function toChecksumAddress (address) {
- return ethereumjsUtil.toChecksumAddress('0x' + address.replace(/^0x/, '').padStart(40, '0'));
- }
- module.exports = function shouldBehaveLikeProxy (createProxy, proxyAdminAddress, proxyCreator) {
- it('cannot be initialized with a non-contract address', async function () {
- const nonContractAddress = proxyCreator;
- const initializeData = Buffer.from('');
- await expectRevert.unspecified(
- createProxy(nonContractAddress, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- }),
- );
- });
- before('deploy implementation', async function () {
- this.implementation = web3.utils.toChecksumAddress((await DummyImplementation.new()).address);
- });
- const assertProxyInitialization = function ({ value, balance }) {
- it('sets the implementation address', async function () {
- const slot = '0x' + new BN(ethereumjsUtil.keccak256(Buffer.from(IMPLEMENTATION_LABEL))).subn(1).toString(16);
- const implementation = toChecksumAddress((await web3.eth.getStorageAt(this.proxy, slot)).substr(-40));
- expect(implementation).to.be.equal(this.implementation);
- });
- it('initializes the proxy', async function () {
- const dummy = new DummyImplementation(this.proxy);
- expect(await dummy.value()).to.be.bignumber.equal(value.toString());
- });
- it('has expected balance', async function () {
- expect(await web3.eth.getBalance(this.proxy)).to.be.bignumber.equal(balance.toString());
- });
- };
- describe('without initialization', function () {
- const initializeData = Buffer.from('');
- describe('when not sending balance', function () {
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- })
- ).address;
- });
- assertProxyInitialization({ value: 0, balance: 0 });
- });
- describe('when sending some balance', function () {
- const value = 10e5;
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- value,
- })
- ).address;
- });
- assertProxyInitialization({ value: 0, balance: value });
- });
- });
- describe('initialization without parameters', function () {
- describe('non payable', function () {
- const expectedInitializedValue = 10;
- const initializeData = new DummyImplementation('').contract.methods['initializeNonPayable()']().encodeABI();
- describe('when not sending balance', function () {
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: 0,
- });
- });
- describe('when sending some balance', function () {
- const value = 10e5;
- it('reverts', async function () {
- await expectRevert.unspecified(
- createProxy(this.implementation, proxyAdminAddress, initializeData, { from: proxyCreator, value }),
- );
- });
- });
- });
- describe('payable', function () {
- const expectedInitializedValue = 100;
- const initializeData = new DummyImplementation('').contract.methods['initializePayable()']().encodeABI();
- describe('when not sending balance', function () {
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: 0,
- });
- });
- describe('when sending some balance', function () {
- const value = 10e5;
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- value,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: value,
- });
- });
- });
- });
- describe('initialization with parameters', function () {
- describe('non payable', function () {
- const expectedInitializedValue = 10;
- const initializeData = new DummyImplementation('').contract
- .methods.initializeNonPayableWithValue(expectedInitializedValue).encodeABI();
- describe('when not sending balance', function () {
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: 0,
- });
- });
- describe('when sending some balance', function () {
- const value = 10e5;
- it('reverts', async function () {
- await expectRevert.unspecified(
- createProxy(this.implementation, proxyAdminAddress, initializeData, { from: proxyCreator, value }),
- );
- });
- });
- });
- describe('payable', function () {
- const expectedInitializedValue = 42;
- const initializeData = new DummyImplementation('').contract
- .methods.initializePayableWithValue(expectedInitializedValue).encodeABI();
- describe('when not sending balance', function () {
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: 0,
- });
- });
- describe('when sending some balance', function () {
- const value = 10e5;
- beforeEach('creating proxy', async function () {
- this.proxy = (
- await createProxy(this.implementation, proxyAdminAddress, initializeData, {
- from: proxyCreator,
- value,
- })
- ).address;
- });
- assertProxyInitialization({
- value: expectedInitializedValue,
- balance: value,
- });
- });
- });
- describe('reverting initialization', function () {
- const initializeData = new DummyImplementation('').contract
- .methods.reverts().encodeABI();
- it('reverts', async function () {
- await expectRevert(
- createProxy(this.implementation, proxyAdminAddress, initializeData, { from: proxyCreator }),
- 'DummyImplementation reverted',
- );
- });
- });
- });
- };
|