Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,17 @@ export async function deploySingleRequestProxy(

const receipt = await tx.wait();

const event = receipt.events?.[0];
const event = receipt.events?.find(
(e) =>
e.event ===
(isERC20 ? 'ERC20SingleRequestProxyCreated' : 'EthereumSingleRequestProxyCreated'),
);

if (!event) {
throw new Error('Single request proxy creation event not found');
}

const proxyAddress = ethers.utils.defaultAbiCoder.decode(['address', 'address'], event.data)[0];
const proxyAddress = event.args?.proxyAddress || event.args?.[0];

if (!proxyAddress) {
throw new Error('Proxy address not found in event data');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ describe('deploySingleRequestProxy', () => {
it('should deploy EthereumSingleRequestProxy and emit event', async () => {
const singleRequestProxyFactory = singleRequestProxyFactoryArtifact.connect('private', wallet);

const initialEventCount = await provider.getBlockNumber();

const walletAddress = await wallet.getAddress();
const initialBlock = await provider.getBlockNumber();

const proxyAddress = await deploySingleRequestProxy(ethRequest, wallet);

Expand All @@ -183,23 +181,31 @@ describe('deploySingleRequestProxy', () => {
const latestBlock = await provider.getBlockNumber();
const events = await singleRequestProxyFactory.queryFilter(
singleRequestProxyFactory.filters.EthereumSingleRequestProxyCreated(),
initialEventCount,
initialBlock,
latestBlock,
);

expect(events.length).toBeGreaterThan(0);

const eventData = utils.defaultAbiCoder.decode(['address', 'address'], events[0].data);

expect(eventData[0]).toBe(proxyAddress);
const event = events[0];
expect(event.args?.proxyAddress).toBe(proxyAddress);
expect(event.args?.payee).toBe(ethRequest.payee?.value);
expect(event.args?.feeAddress).toBe(
ethRequest.extensions[ExtensionTypes.PAYMENT_NETWORK_ID.ETH_FEE_PROXY_CONTRACT].values
.feeAddress,
);
expect(event.args?.feeAmount.toString()).toBe(
ethRequest.extensions[ExtensionTypes.PAYMENT_NETWORK_ID.ETH_FEE_PROXY_CONTRACT].values
.feeAmount,
);
const feeProxyUsed = await singleRequestProxyFactory.ethereumFeeProxy();
expect(event.args?.feeProxyUsed).toBe(feeProxyUsed);
});

it('should deploy ERC20SingleRequestProxy and emit event', async () => {
const singleRequestProxyFactory = singleRequestProxyFactoryArtifact.connect('private', wallet);

const initialEventCount = await provider.getBlockNumber();

const walletAddress = await wallet.getAddress();
const initialBlock = await provider.getBlockNumber();

const proxyAddress = await deploySingleRequestProxy(erc20Request, wallet);

Expand All @@ -210,15 +216,26 @@ describe('deploySingleRequestProxy', () => {
const latestBlock = await provider.getBlockNumber();
const events = await singleRequestProxyFactory.queryFilter(
singleRequestProxyFactory.filters.ERC20SingleRequestProxyCreated(),
initialEventCount,
initialBlock,
latestBlock,
);

expect(events.length).toBeGreaterThan(0);

const eventData = utils.defaultAbiCoder.decode(['address', 'address'], events[0].data);

expect(eventData[0]).toBe(proxyAddress);
const event = events[0];
expect(event.args?.proxyAddress).toBe(proxyAddress);
expect(event.args?.payee).toBe(erc20Request.payee?.value);
expect(event.args?.tokenAddress).toBe(erc20Request.currencyInfo.value);
expect(event.args?.feeAddress).toBe(
erc20Request.extensions[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_FEE_PROXY_CONTRACT].values
.feeAddress,
);
expect(event.args?.feeAmount.toString()).toBe(
erc20Request.extensions[ExtensionTypes.PAYMENT_NETWORK_ID.ERC20_FEE_PROXY_CONTRACT].values
.feeAmount,
);
const feeProxyUsed = await singleRequestProxyFactory.erc20FeeProxy();
expect(event.args?.feeProxyUsed).toBe(feeProxyUsed);
});

it('should throw error when trying to pay with invalid single request proxy', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ import './lib/SafeERC20.sol';
contract ERC20SingleRequestProxy {
address public payee;
address public tokenAddress;
bytes public paymentReference;
address public feeAddress;
uint256 public feeAmount;
bytes public paymentReference;
IERC20FeeProxy public erc20FeeProxy;

constructor(
address _payee,
address _tokenAddress,
bytes memory _paymentReference,
address _feeAddress,
uint256 _feeAmount,
bytes memory _paymentReference,
address _erc20FeeProxy
) {
payee = _payee;
tokenAddress = _tokenAddress;
paymentReference = _paymentReference;
feeAddress = _feeAddress;
feeAmount = _feeAmount;
paymentReference = _paymentReference;
erc20FeeProxy = IERC20FeeProxy(_erc20FeeProxy);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ contract EthereumSingleRequestProxy {
constructor(
address _payee,
bytes memory _paymentReference,
address _ethereumFeeProxy,
address _feeAddress,
uint256 _feeAmount
uint256 _feeAmount,
address _ethereumFeeProxy
) {
payee = _payee;
paymentReference = _paymentReference;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,20 @@ contract SingleRequestProxyFactory is Ownable {
event EthereumSingleRequestProxyCreated(
address proxyAddress,
address payee,
bytes indexed paymentReference
bytes indexed paymentReference,
address feeAddress,
uint256 feeAmount,
address feeProxyUsed
);

event ERC20SingleRequestProxyCreated(
address proxyAddress,
address payee,
address tokenAddress,
bytes indexed paymentReference
bytes indexed paymentReference,
address feeAddress,
uint256 feeAmount,
address feeProxyUsed
);

event ERC20FeeProxyUpdated(address indexed newERC20FeeProxy);
Expand Down Expand Up @@ -60,11 +66,18 @@ contract SingleRequestProxyFactory is Ownable {
EthereumSingleRequestProxy proxy = new EthereumSingleRequestProxy(
_payee,
_paymentReference,
ethereumFeeProxy,
_feeAddress,
_feeAmount
_feeAmount,
ethereumFeeProxy
);
emit EthereumSingleRequestProxyCreated(
address(proxy),
_payee,
_paymentReference,
_feeAddress,
_feeAmount,
ethereumFeeProxy
);
emit EthereumSingleRequestProxyCreated(address(proxy), _payee, _paymentReference);
return address(proxy);
}

Expand All @@ -87,13 +100,21 @@ contract SingleRequestProxyFactory is Ownable {
ERC20SingleRequestProxy proxy = new ERC20SingleRequestProxy(
_payee,
_tokenAddress,
_paymentReference,
_feeAddress,
_feeAmount,
_paymentReference,
erc20FeeProxy
);

emit ERC20SingleRequestProxyCreated(address(proxy), _payee, _tokenAddress, _paymentReference);
emit ERC20SingleRequestProxyCreated(
address(proxy),
_payee,
_tokenAddress,
_paymentReference,
_feeAddress,
_feeAmount,
erc20FeeProxy
);
return address(proxy);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,24 @@
"internalType": "bytes",
"name": "paymentReference",
"type": "bytes"
},
{
"indexed": false,
"internalType": "address",
"name": "feeAddress",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "feeAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "address",
"name": "feeProxyUsed",
"type": "address"
}
],
"name": "ERC20SingleRequestProxyCreated",
Expand Down Expand Up @@ -98,6 +116,24 @@
"internalType": "bytes",
"name": "paymentReference",
"type": "bytes"
},
{
"indexed": false,
"internalType": "address",
"name": "feeAddress",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "feeAmount",
"type": "uint256"
},
{
"indexed": false,
"internalType": "address",
"name": "feeProxyUsed",
"type": "address"
}
],
"name": "EthereumSingleRequestProxyCreated",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ export const singleRequestProxyFactoryArtifact = new ContractArtifact<SingleRequ
creationBlockNumber: 0,
},
sepolia: {
address: '0x435E81E12136414e2c09cAFe05E902E23bD46030',
creationBlockNumber: 6965557,
address: '0xf8cACE7EE4c03Eb4f225434B0709527938D365b4',
creationBlockNumber: 7038199,
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ describe('contract: ERC20SingleRequestProxy', () => {
erc20SingleRequestProxy = await new ERC20SingleRequestProxy__factory(deployer).deploy(
user2Addr,
testToken.address,
paymentReference,
feeRecipientAddr,
feeAmount,
paymentReference,
erc20FeeProxy.address,
);

Expand Down Expand Up @@ -156,9 +156,9 @@ describe('contract: ERC20SingleRequestProxy', () => {
const usdtProxy = await new ERC20SingleRequestProxy__factory(deployer).deploy(
user2Addr,
usdtFake.address,
paymentReference,
feeRecipientAddr,
usdtFeeAmount,
paymentReference,
erc20FeeProxy.address,
);

Expand Down Expand Up @@ -210,9 +210,9 @@ describe('contract: ERC20SingleRequestProxy', () => {
const zeroFeeProxy = await new ERC20SingleRequestProxy__factory(deployer).deploy(
user2Addr,
testToken.address,
paymentReference,
feeRecipientAddr,
0,
paymentReference,
erc20FeeProxy.address,
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ describe('contract : EthereumSingleRequestProxy', () => {
ethereumSingleRequestProxy = await ethereumSingleRequestProxyFactory.deploy(
payeeAddress,
paymentReference,
ethereumFeeProxy.address,
feeRecipientAddress,
feeAmount,
ethereumFeeProxy.address,
);
await ethereumSingleRequestProxy.deployed();
});
Expand Down Expand Up @@ -87,9 +87,9 @@ describe('contract : EthereumSingleRequestProxy', () => {
const newEthereumSingleRequestProxy = await newEthereumSingleRequestProxyFactory.deploy(
payeeAddress,
paymentReference,
mockEthereumFeeProxy.address,
feeRecipientAddress,
feeAmount,
mockEthereumFeeProxy.address,
);
await newEthereumSingleRequestProxy.deployed();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,16 @@ describe('contract: SingleRequestProxyFactory', () => {
expect(proxyAddress).to.not.equal(ethers.constants.AddressZero);
expect(proxyAddress).to.be.properAddress;

// Check if the event was emitted with correct parameters
await expect(tx)
.to.emit(singleRequestProxyFactory, 'EthereumSingleRequestProxyCreated')
.withArgs(proxyAddress, payeeAddress, paymentReference);
.withArgs(
proxyAddress,
payeeAddress,
paymentReference,
feeRecipientAddress,
feeAmount,
ethereumFeeProxy.address,
);

const proxy = (await ethers.getContractAt(
'EthereumSingleRequestProxy',
Expand Down Expand Up @@ -119,10 +125,17 @@ describe('contract: SingleRequestProxyFactory', () => {
expect(proxyAddress).to.not.equal(ethers.constants.AddressZero);
expect(proxyAddress).to.be.properAddress;

// Check if the event was emitted with correct parameters
await expect(tx)
.to.emit(singleRequestProxyFactory, 'ERC20SingleRequestProxyCreated')
.withArgs(proxyAddress, payeeAddress, testToken.address, paymentReference);
.withArgs(
proxyAddress,
payeeAddress,
testToken.address,
paymentReference,
feeRecipientAddress,
feeAmount,
erc20FeeProxy.address,
);

const proxy = (await ethers.getContractAt(
'ERC20SingleRequestProxy',
Expand Down