Skip to content

Commit

Permalink
hiddenSalt -> Metadata on joinGame method
Browse files Browse the repository at this point in the history
  • Loading branch information
peersky committed Feb 8, 2025
1 parent b63982c commit 13c5876
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 43 deletions.
3 changes: 2 additions & 1 deletion playbook/createSubject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ task('createSubject', 'Creates a new subject with MAO distribution')
'Distributors ID to create game from, defaults to hardhat task defaultDistributionId',
)
.setAction(async (taskArgs, hre) => {
const { getNamedAccounts } = hre;
const { getNamedAccounts, deployments } = hre;
await deployments.fixture(['MAO']);
const distributorDeployment = await hre.deployments.get('DAODistributor');

const distributorArguments: MAODistribution.DistributorArgumentsStruct = {
Expand Down
12 changes: 6 additions & 6 deletions scripts/EnvironmentSimulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ class EnvironmentSimulator {
{ type: 'address', name: 'instance' },
{ type: 'address', name: 'participant' },
{ type: 'uint256', name: 'gameId' },
{ type: 'bytes32', name: 'hiddenSalt' },
{ type: 'bytes32', name: 'metadata' },
],
};
/**
Expand All @@ -932,14 +932,14 @@ class EnvironmentSimulator {
chainId,
verifyingContract: this.rankifyInstance.address,
};
const hiddenSalt = ethers.utils.hexZeroPad('0x123131231311', 32); // Pad to 32 bytes
const metadata = ethers.utils.hexZeroPad('0x123131231311', 32); // Pad to 32 bytes
const signature = await signer._signTypedData(domain, this.joinTypes, {
instance: this.rankifyInstance.address,
participant,
gameId,
hiddenSalt: ethers.utils.keccak256(hiddenSalt), // Hash the padded value
metadata: ethers.utils.keccak256(metadata), // Hash the padded value
});
return { signature, hiddenSalt };
return { signature, metadata };
};

public async createGame(
Expand Down Expand Up @@ -1394,8 +1394,8 @@ class EnvironmentSimulator {
.connect(players[i].wallet)
.setApprovalForAll(this.rankifyInstance.address, true)
.then(tx => tx.wait(1));
const { signature, hiddenSalt } = await this.signJoiningGame(gameId, players[i].wallet.address, gameMaster);
promises.push(await this.rankifyInstance.connect(players[i].wallet).joinGame(gameId, signature, hiddenSalt));
const { signature, metadata } = await this.signJoiningGame(gameId, players[i].wallet.address, gameMaster);
promises.push(await this.rankifyInstance.connect(players[i].wallet).joinGame(gameId, signature, metadata));
}
}
if (shiftTime) {
Expand Down
10 changes: 6 additions & 4 deletions src/facets/RankifyInstanceMainFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ contract RankifyInstanceMainFacet is
/**
* @dev Allows a player to join a game with the provided game ID. `gameId` is the ID of the game.
* @param gameId The ID of the game.
* @param gameMasterSignature The ECDSA signature of the game master.
* @param metadata The metadata of the player signed by the game master.
* @notice This function:
* - Calls the `joinGame` function with `msg.sender`.
* - Calls the `fund` function with `bytes32(gameId)`.
Expand All @@ -161,24 +163,24 @@ contract RankifyInstanceMainFacet is
function joinGame(
uint256 gameId,
bytes memory gameMasterSignature,
bytes memory hiddenSalt
bytes memory metadata
) public payable nonReentrant {
bytes32 digest = _hashTypedDataV4(
keccak256(
abi.encode(
keccak256(
"AttestJoiningGame(address instance,address participant,uint256 gameId,bytes32 hiddenSalt)"
"AttestJoiningGame(address instance,address participant,uint256 gameId,bytes32 metadata)"
),
address(this),
msg.sender,
gameId,
keccak256(hiddenSalt)
keccak256(metadata)
)
)
);
gameId.joinGame(msg.sender, gameMasterSignature, digest);
LibCoinVending.fund(bytes32(gameId));
emit PlayerJoined(gameId, msg.sender, hiddenSalt);
emit PlayerJoined(gameId, msg.sender, metadata);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IRankifyInstance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface IRankifyInstance {
error RankNotSpecified();

event RegistrationOpen(uint256 indexed gameId);
event PlayerJoined(uint256 indexed gameId, address indexed participant, bytes hiddenSalt);
event PlayerJoined(uint256 indexed gameId, address indexed participant, bytes metadata);
event GameStarted(uint256 indexed gameId);
event gameCreated(uint256 gameId, address indexed gm, address indexed creator, uint256 indexed rank);
event GameClosed(uint256 indexed gameId);
Expand Down
62 changes: 31 additions & 31 deletions test/RankifyInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ describe(scriptName, () => {
it('Cannot perform actions on games that do not exist', async () => {
const s1 = await simulator.signJoiningGame(1, adr.gameCreator1.wallet.address, adr.gameMaster1);
await expect(
rankifyInstance.connect(adr.gameCreator1.wallet).joinGame(1, s1.signature, s1.hiddenSalt),
rankifyInstance.connect(adr.gameCreator1.wallet).joinGame(1, s1.signature, s1.metadata),
).to.be.revertedWith('game not found');
let proposals = await simulator.mockProposals({
players: simulator.getPlayers(adr, RInstance_MAX_PLAYERS),
Expand Down Expand Up @@ -477,7 +477,7 @@ describe(scriptName, () => {

const s2 = await simulator.signJoiningGame(1, adr.gameMaster1.address, adr.gameMaster1);

await expect(rankifyInstance.connect(adr.gameMaster1).joinGame(0, s2.signature, s2.hiddenSalt)).to.be.revertedWith(
await expect(rankifyInstance.connect(adr.gameMaster1).joinGame(0, s2.signature, s2.metadata)).to.be.revertedWith(
'game not found',
);
await expect(
Expand Down Expand Up @@ -625,7 +625,7 @@ describe(scriptName, () => {
const gameId = await rankifyInstance.getContractState().then(s => s.numGames);
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(gameId, s1.signature, s1.hiddenSalt),
rankifyInstance.connect(adr.players[0].wallet).joinGame(gameId, s1.signature, s1.metadata),
).to.be.revertedWith('addPlayer->cant join now');
});
it('Allows only game creator to add join requirements', async () => {
Expand Down Expand Up @@ -657,22 +657,21 @@ describe(scriptName, () => {
// Try with wrong signer
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster2); // Using wrong game master
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.hiddenSalt),
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.metadata),
).to.be.revertedWithCustomError(rankifyInstance, 'invalidECDSARecoverSigner');

// Try with wrong gameId
const s2 = await signJoiningGame(2, adr.players[0].wallet.address, adr.gameMaster1); // Wrong gameId
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s2.signature, s2.hiddenSalt),
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s2.signature, s2.metadata),
).to.be.revertedWithCustomError(rankifyInstance, 'invalidECDSARecoverSigner');

// Try with wrong participant
const s3 = await signJoiningGame(1, adr.players[1].wallet.address, adr.gameMaster1); // Wrong participant
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s3.signature, s3.hiddenSalt),
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s3.signature, s3.metadata),
).to.be.revertedWithCustomError(rankifyInstance, 'invalidECDSARecoverSigner');

// Try with tampered hiddenSalt
const s4 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
const tamperedSalt = eth.utils.hexZeroPad('0xdeadbeef', 32); // Different salt than what was signed
await expect(
Expand All @@ -682,9 +681,9 @@ describe(scriptName, () => {

it('Should accept valid signature from correct game master', async () => {
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
await expect(rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.hiddenSalt))
await expect(rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.metadata))
.to.emit(rankifyInstance, 'PlayerJoined')
.withArgs(1, adr.players[0].wallet.address, s1.hiddenSalt);
.withArgs(1, adr.players[0].wallet.address, s1.metadata);
});

it('Mutating join requirements is no longer possible', async () => {
Expand All @@ -694,13 +693,14 @@ describe(scriptName, () => {
});
it('Qualified players can join', async () => {
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.hiddenSalt),
).to.be.emit(rankifyInstance, 'PlayerJoined');
await expect(rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.metadata)).to.be.emit(
rankifyInstance,
'PlayerJoined',
);
});
it('Game cannot be started until join block time has passed unless game is full', async () => {
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.metadata);
await expect(
rankifyInstance.connect(adr.players[0].wallet).startGame(
1,
Expand All @@ -715,15 +715,15 @@ describe(scriptName, () => {
),
).to.be.revertedWith('startGame->Not enough players');
const s2 = await signJoiningGame(1, adr.players[1].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[1].wallet).joinGame(1, s2.signature, s2.hiddenSalt);
await rankifyInstance.connect(adr.players[1].wallet).joinGame(1, s2.signature, s2.metadata);
const s3 = await signJoiningGame(1, adr.players[2].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[2].wallet).joinGame(1, s3.signature, s3.hiddenSalt);
await rankifyInstance.connect(adr.players[2].wallet).joinGame(1, s3.signature, s3.metadata);
const s4 = await signJoiningGame(1, adr.players[3].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[3].wallet).joinGame(1, s4.signature, s4.hiddenSalt);
await rankifyInstance.connect(adr.players[3].wallet).joinGame(1, s4.signature, s4.metadata);
const s5 = await signJoiningGame(1, adr.players[4].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[4].wallet).joinGame(1, s5.signature, s5.hiddenSalt);
await rankifyInstance.connect(adr.players[4].wallet).joinGame(1, s5.signature, s5.metadata);
const s6 = await signJoiningGame(1, adr.players[5].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[5].wallet).joinGame(1, s6.signature, s6.hiddenSalt);
await rankifyInstance.connect(adr.players[5].wallet).joinGame(1, s6.signature, s6.metadata);
await expect(
rankifyInstance.connect(adr.players[0].wallet).startGame(
1,
Expand All @@ -741,19 +741,19 @@ describe(scriptName, () => {
it('No more than max players can join', async () => {
for (let i = 1; i < RInstance_MAX_PLAYERS + 1; i++) {
const s1 = await signJoiningGame(1, adr.players[i].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[i].wallet).joinGame(1, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(adr.players[i].wallet).joinGame(1, s1.signature, s1.metadata);
}
await env.rankifyToken
.connect(adr.maliciousActor1.wallet)
.approve(rankifyInstance.address, eth.constants.MaxUint256);
const s1 = await signJoiningGame(1, adr.maliciousActor1.wallet.address, adr.gameMaster1);
await expect(
rankifyInstance.connect(adr.maliciousActor1.wallet).joinGame(1, s1.signature, s1.hiddenSalt),
rankifyInstance.connect(adr.maliciousActor1.wallet).joinGame(1, s1.signature, s1.metadata),
).to.be.revertedWith('addPlayer->party full');
});
it('Game methods beside join and start are inactive', async () => {
const s1 = await signJoiningGame(1, adr.players[0].wallet.address, adr.gameMaster1);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(1, s1.signature, s1.metadata);
const proposals = await mockProposals({
players: getPlayers(adr, RInstance_MAX_PLAYERS),
gameId: 1,
Expand Down Expand Up @@ -1411,7 +1411,7 @@ describe(scriptName, () => {
it('Reverts if players from another game tries to join', async () => {
const s1 = await simulator.signJoiningGame(2, adr.players[0].wallet.address, adr.gameMaster1);
await expect(
rankifyInstance.connect(adr.players[0].wallet).joinGame(2, s1.signature, s1.hiddenSalt),
rankifyInstance.connect(adr.players[0].wallet).joinGame(2, s1.signature, s1.metadata),
).to.be.revertedWith('addPlayer->Player in game');
});
});
Expand Down Expand Up @@ -1693,11 +1693,11 @@ describe(scriptName, () => {
await rankToken.connect(adr.players[1].wallet).setApprovalForAll(rankifyInstance.address, true);
const s1 = await simulator.signJoiningGame(2, adr.players[0].wallet.address, adr.gameMaster1);
const s2 = await simulator.signJoiningGame(2, adr.players[1].wallet.address, adr.gameMaster1);
await expect(rankifyInstance.connect(adr.players[0].wallet).joinGame(2, s1.signature, s1.hiddenSalt))
await expect(rankifyInstance.connect(adr.players[0].wallet).joinGame(2, s1.signature, s1.metadata))
.to.emit(rankifyInstance, 'PlayerJoined')
.withArgs(2, adr.players[0].wallet.address, s1.hiddenSalt);
.withArgs(2, adr.players[0].wallet.address, s1.metadata);
await expect(
rankifyInstance.connect(adr.players[1].wallet).joinGame(2, s2.signature, s2.hiddenSalt),
rankifyInstance.connect(adr.players[1].wallet).joinGame(2, s2.signature, s2.metadata),
).to.be.revertedWithCustomError(rankToken, 'insufficient');
});
});
Expand Down Expand Up @@ -1742,7 +1742,7 @@ describe(scriptName, () => {
winnerPlayer.wallet.address,
simulator.adr.gameMaster1,
);
await rankifyInstance.connect(winnerPlayer.wallet).joinGame(state.numGames, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(winnerPlayer.wallet).joinGame(state.numGames, s1.signature, s1.metadata);
const currentT = await time.latest();
await time.setNextBlockTimestamp(currentT + Number(RInstance_TIME_TO_JOIN) + 1);
const loser = players.find(p => p.wallet.address != winnerPlayer.wallet.address);
Expand All @@ -1753,7 +1753,7 @@ describe(scriptName, () => {

const s2 = await simulator.signJoiningGame(state.numGames, loser.wallet.address, simulator.adr.gameMaster1);
await expect(
rankifyInstance.connect(loser.wallet).joinGame(state.numGames, s2.signature, s2.hiddenSalt),
rankifyInstance.connect(loser.wallet).joinGame(state.numGames, s2.signature, s2.metadata),
).to.be.revertedWithCustomError(rankToken, 'insufficient');
});
});
Expand Down Expand Up @@ -1928,7 +1928,7 @@ describe(scriptName + '::Multiple games were played', () => {
simulator.adr.gameMaster1,
);
await expect(
rankifyInstance.connect(adr.players[1].wallet).joinGame(lastCreatedGameId, s2.signature, s2.hiddenSalt),
rankifyInstance.connect(adr.players[1].wallet).joinGame(lastCreatedGameId, s2.signature, s2.metadata),
).to.emit(rankifyInstance, 'PlayerJoined');
await rankToken.connect(adr.maliciousActor1.wallet).setApprovalForAll(rankifyInstance.address, true);
const mal1s = await simulator.signJoiningGame(
Expand All @@ -1939,7 +1939,7 @@ describe(scriptName + '::Multiple games were played', () => {
await expect(
rankifyInstance
.connect(adr.maliciousActor1.wallet)
.joinGame(lastCreatedGameId, mal1s.signature, mal1s.hiddenSalt),
.joinGame(lastCreatedGameId, mal1s.signature, mal1s.metadata),
).to.be.revertedWithCustomError(rankToken, 'insufficient');
});
it('Locks rank tokens when player joins', async () => {
Expand All @@ -1951,7 +1951,7 @@ describe(scriptName + '::Multiple games were played', () => {
adr.players[0].wallet.address,
simulator.adr.gameMaster1,
);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(lastCreatedGameId, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(lastCreatedGameId, s1.signature, s1.metadata);
const balance2 = await rankToken.balanceOf(adr.players[0].wallet.address, 2);
expect(await rankToken.unlockedBalanceOf(adr.players[0].wallet.address, 2)).to.be.equal(balance.toNumber() - 1);
});
Expand All @@ -1973,7 +1973,7 @@ describe(scriptName + '::Multiple games were played', () => {
simulator.adr.gameMaster1,
);

await rankifyInstance.connect(adr.players[0].wallet).joinGame(lastCreatedGameId, s1.signature, s1.hiddenSalt);
await rankifyInstance.connect(adr.players[0].wallet).joinGame(lastCreatedGameId, s1.signature, s1.metadata);
let p1balance = await rankToken.unlockedBalanceOf(adr.players[0].wallet.address, 2);
p1balance = p1balance.add(1);

Expand Down

0 comments on commit 13c5876

Please sign in to comment.