Contract Name:
PeerToPlayImplementationM1
Contract Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Variables} from "../variables.sol";
/**
* @title PeerToPlayAccount
* @dev Smart contract for managing PeerToPlay smart account wallet.
*/
interface ConnectorsInterface {
/**
* @dev Checks if the provided connector names are valid and returns their corresponding addresses.
* @param connectorNames Array of connector names to validate.
* @return bool indicating if all names are valid, and an array of connector addresses.
*/
function isConnectors(
string[] calldata connectorNames
) external view returns (bool, address[] memory);
}
/**
* @title Constants
* @dev Contract that defines immutable constants such as the factory and connectors addresses.
*/
contract Constants is Variables {
// Address of the PeerToPlayFactory contract.
address internal immutable peerToPlayFactory;
// Address of the connectors module.
address public immutable connectorsM1;
constructor(address _peerToPlayFactory, address _connectors) {
connectorsM1 = _connectors;
peerToPlayFactory = _peerToPlayFactory;
}
}
/**
* @title PeerToPlayImplementationM1
* @dev Contract for executing delegated calls to connectors for PeerToPlay smart accounts.
*/
contract PeerToPlayImplementationM1 is Constants {
constructor(
address _peerToPlayFactory,
address _connectors
) Constants(_peerToPlayFactory, _connectors) {}
/**
* @dev Decodes the event data from the response of a delegated call.
* @param response The response bytes from the call.
* @return _eventCode The event code as a string.
* @return _eventParams The parameters of the event as bytes.
*/
function decodeEvent(
bytes memory response
)
internal
pure
returns (string memory _eventCode, bytes memory _eventParams)
{
if (response.length > 0) {
(_eventCode, _eventParams) = abi.decode(response, (string, bytes));
}
}
/**
* @dev Emitted when a cast operation is executed from the PeerToPlay account.
* @param origin The origin address initiating the cast.
* @param sender The sender address performing the cast.
* @param value The amount of Ether sent with the cast.
* @param targetsNames The names of the target connectors.
* @param targets The addresses of the target connectors.
* @param eventNames The names of the events triggered.
* @param eventParams The parameters of the triggered events.
*/
event LogCast(
address indexed origin,
address indexed sender,
uint256 value,
string[] targetsNames,
address[] targets,
string[] eventNames,
bytes[] eventParams
);
receive() external payable {}
/**
* @dev Delegate a call to a connector.
* @param _target The address of the connector to delegate to.
* @param _data The calldata for the function call.
* @return response The response bytes from the delegated call.
*/
function spell(
address _target,
bytes memory _data
) internal returns (bytes memory response) {
require(_target != address(0), "target-invalid");
assembly {
let succeeded := delegatecall(
gas(),
_target,
add(_data, 0x20),
mload(_data),
0,
0
)
let size := returndatasize()
response := mload(0x40)
mstore(
0x40,
add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))
)
mstore(response, size)
returndatacopy(add(response, 0x20), 0, size)
switch iszero(succeeded)
case 1 {
// Revert if the delegatecall failed
returndatacopy(0x00, 0x00, size)
revert(0x00, size)
}
}
}
/**
* @dev Executes multiple delegated calls to connectors.
* @param _targetNames An array of target connector names.
* @param _datas An array of calldata for each target connector.
* @param _origin The address that initiated the cast.
* @return Dummy return value to comply with PeerToPlayFactory buildWithCast function.
*/
function cast(
string[] calldata _targetNames,
bytes[] calldata _datas,
address _origin
)
external
payable
returns (
bytes32 // Dummy return to fix PeerToPlayFactory buildWithCast function
)
{
uint256 _length = _targetNames.length;
require(
_auth[msg.sender] || msg.sender == peerToPlayFactory,
"1: permission-denied"
);
require(_length != 0, "1: length-invalid");
require(_length == _datas.length, "1: array-length-invalid");
string[] memory eventNames = new string[](_length);
bytes[] memory eventParams = new bytes[](_length);
(bool isOk, address[] memory _targets) = ConnectorsInterface(
connectorsM1
).isConnectors(_targetNames);
require(isOk, "1: not-connector");
for (uint i = 0; i < _length; i++) {
bytes memory response = spell(_targets[i], _datas[i]);
(eventNames[i], eventParams[i]) = decodeEvent(response);
}
emit LogCast(
_origin,
msg.sender,
msg.value,
_targetNames,
_targets,
eventNames,
eventParams
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Variables
* @dev This contract manages the authorization settings for the platform.
*/
contract Variables {
/// @dev Mapping of address to boolean indicating authorization status.
mapping (address => bool) internal _auth;
}