Skip to content
This repository was archived by the owner on Jul 4, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions contracts/DullahanPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract DullahanPod is ReentrancyGuard {
/** @notice Is the Pod initialized */
bool public initialized;

/** @notice Address of the Pod manager */
/** @notice Address of the PodManager contract */
address public manager;
/** @notice Address of the Vault */
address public vault;
Expand All @@ -53,6 +53,8 @@ contract DullahanPod is ReentrancyGuard {

/** @notice Address of the Pod owner */
address public podOwner;
/** @notice Address of the Pod Proxy owner, allowed to control the Pod for the owner */
address public podProxyOwner;

/** @notice Address of the delegate receiving the Pod voting power */
address public votingPowerDelegate;
Expand Down Expand Up @@ -101,12 +103,17 @@ contract DullahanPod is ReentrancyGuard {
/** @notice Event emitted when the Pod registry is updated */
event UpdatedRegistry(address indexed oldRegistry, address indexed newRegistry);

/** @notice Event emitted when the proxyOwner is updated */
event ProxyOwnerUpdated(address indexed newProxyOwner);
/** @notice Event emitted when the proxyOwner is forfeited */
event ProxyOwnerForfeited();


// Modifers

/** @notice Check that the caller is the Pod owner */
/** @notice Check that the caller is the Pod owner or the proxy onwer */
modifier onlyPodOwner() {
if(msg.sender != podOwner) revert Errors.NotPodOwner();
if(msg.sender != podOwner && msg.sender != podProxyOwner) revert Errors.NotPodOwner();
_;
}

Expand All @@ -131,6 +138,7 @@ contract DullahanPod is ReentrancyGuard {
registry = address(0xdEaD);
collateral = address(0xdEaD);
podOwner = address(0xdEaD);
podProxyOwner = address(0xdEaD);
votingPowerDelegate = address(0xdEaD);
proposalPowerDelegate = address(0xdEaD);
}
Expand All @@ -141,6 +149,7 @@ contract DullahanPod is ReentrancyGuard {
* @param _vault Address of the Vault
* @param _registry Address of the Registry
* @param _podOwner Address of the Pod owner
* @param _podProxyOwner Address of the Pod proxy owner
* @param _collateral Address of the collateral
* @param _aToken Address of the aToken for the collateral
* @param _votingPowerDelegate Address of the delegate for the voting power
Expand All @@ -151,6 +160,7 @@ contract DullahanPod is ReentrancyGuard {
address _vault,
address _registry,
address _podOwner,
address _podProxyOwner,
address _collateral,
address _aToken,
address _votingPowerDelegate,
Expand Down Expand Up @@ -179,6 +189,10 @@ contract DullahanPod is ReentrancyGuard {
votingPowerDelegate = _votingPowerDelegate;
proposalPowerDelegate = _proposalPowerDelegate;

if(_podProxyOwner != address(0)) {
podProxyOwner = _podProxyOwner;
}

aToken = _aToken;

// Fetch the stkAAVE address from the Registry
Expand Down Expand Up @@ -387,6 +401,31 @@ contract DullahanPod is ReentrancyGuard {
return true;
}

/**
* @notice Change the podProxyOwner for this Pod
* @dev Allow the Pod owner or the current proxy owner to change the proxy owner
* @param newProxyOwner Address of the new podProxyOwner
*/
function changeProxyOwner(address newProxyOwner) external isInitialized onlyPodOwner {
if(newProxyOwner == podProxyOwner) revert Errors.SameAddress();

podProxyOwner = newProxyOwner;

emit ProxyOwnerUpdated(newProxyOwner);
}

/**
* @notice Forfeit the Pod proxy ownership rights
* @dev Forfeit the Pod proxy ownership rights, only callable by the current podProxyOwner
*/
function forfeitProxyOwnserhip() external isInitialized {
if(msg.sender != podProxyOwner) revert Errors.NotPodProxyOwner();

podProxyOwner = address(0);

emit ProxyOwnerForfeited();
}


// Manager only functions

Expand Down
16 changes: 8 additions & 8 deletions contracts/DullahanPodManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,13 @@ contract DullahanPodManager is ReentrancyGuard, Pausable, Owner {
* @return address : Address of the newly deployed Pod
*/
function createPod(
address collateral
address collateral,
address owner
) external nonReentrant whenNotPaused returns(address) {
if(collateral == address(0)) revert Errors.AddressZero();
if(collateral == address(0) || owner == address(0)) revert Errors.AddressZero();
if(!allowedCollaterals[collateral]) revert Errors.CollateralNotAllowed();
if(!_updateGlobalState()) revert Errors.FailStateUpdate();

address podOwner = msg.sender;

// Clone to create new Pod
address newPod = Clones.clone(podImplementation);

Expand All @@ -339,7 +338,8 @@ contract DullahanPodManager is ReentrancyGuard, Pausable, Owner {
address(this),
vault,
registry,
podOwner,
owner,
owner == msg.sender ? address(0) : msg.sender,
collateral,
aTokenForCollateral[collateral],
votingPowerDelegate,
Expand All @@ -348,12 +348,12 @@ contract DullahanPodManager is ReentrancyGuard, Pausable, Owner {

// Write the new Pod data in storage
pods[newPod].podAddress = newPod;
pods[newPod].podOwner = podOwner;
pods[newPod].podOwner = owner;
pods[newPod].collateral = collateral;
allPods.push(newPod);
ownerPods[podOwner].push(newPod);
ownerPods[owner].push(newPod);

emit PodCreation(collateral, podOwner, newPod);
emit PodCreation(collateral, owner, newPod);

return newPod;
}
Expand Down
3 changes: 3 additions & 0 deletions contracts/test/MockPod.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract MockPod {
address public registry;

address public podOwner;
address public podProxyOwner;

address public votingPowerDelegate;
address public proposalPowerDelegate;
Expand All @@ -33,6 +34,7 @@ contract MockPod {
address _vault,
address _registry,
address _podOwner,
address _podProxyOwner,
address _collateral,
address _aToken,
address _votingPowerDelegate,
Expand All @@ -44,6 +46,7 @@ contract MockPod {
vault = _vault;
registry = _registry;
podOwner = _podOwner;
podProxyOwner = _podProxyOwner;
collateral = _collateral;
votingPowerDelegate = _votingPowerDelegate;
proposalPowerDelegate = _proposalPowerDelegate;
Expand Down
1 change: 1 addition & 0 deletions contracts/utils/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ library Errors {
error FailPodStateUpdate();
error MintAmountUnderMinimum();
error RepayFailed();
error NotPodProxyOwner();

// Pods Manager Errors
error CallerNotValidPod();
Expand Down
3 changes: 3 additions & 0 deletions scripts/others/Pod-v2-fork-deploys.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Pod Impl : 0x5796d6346b515cc3997e764dd32103f9ae09fb80

Pod Manager : 0x597f2af53babb9faaf50c81bf733d3fcf976e579
17 changes: 9 additions & 8 deletions test/fork-test-main/fullSystem.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

it(' should create a new Pod correctly', async () => {

const create_tx = await manager.connect(podOwner).createPod(token1.address)
const create_tx = await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
const new_pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand All @@ -284,6 +284,7 @@ describe('Dullahan full system tests - Mainnet version', () => {
expect(await new_pod.collateral()).to.be.eq(token1.address)
expect(await new_pod.aToken()).to.be.eq(aToken1.address)
expect(await new_pod.podOwner()).to.be.eq(podOwner.address)
expect(await new_pod.podProxyOwner()).to.be.eq(ethers.constants.AddressZero)
expect(await new_pod.votingPowerDelegate()).to.be.eq(votingManager.address)
expect(await new_pod.proposalPowerDelegate()).to.be.eq(votingManager.address)
expect(await new_pod.aave()).to.be.eq(aave.address)
Expand Down Expand Up @@ -324,7 +325,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

beforeEach(async () => {

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand Down Expand Up @@ -392,7 +393,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

beforeEach(async () => {

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand Down Expand Up @@ -480,7 +481,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

beforeEach(async () => {

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand Down Expand Up @@ -610,7 +611,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

await gho.connect(admin).transfer(podOwner.address, ethers.utils.parseEther('50000'))

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand Down Expand Up @@ -688,7 +689,7 @@ describe('Dullahan full system tests - Mainnet version', () => {

await gho.connect(admin).transfer(podOwner.address, ethers.utils.parseEther('50000'))

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 1], provider);
Expand Down Expand Up @@ -843,8 +844,8 @@ describe('Dullahan full system tests - Mainnet version', () => {

await gho.connect(admin).transfer(podOwner.address, ethers.utils.parseEther('50000'))

await manager.connect(podOwner).createPod(token1.address)
await manager.connect(podOwner).createPod(token2.address)
await manager.connect(podOwner).createPod(token1.address, podOwner.address)
await manager.connect(podOwner).createPod(token2.address, podOwner.address)

const podList = await manager.getAllPods()
pod = DullahanPod__factory.connect(podList[podList.length - 2], provider);
Expand Down
14 changes: 7 additions & 7 deletions test/unit-test/manager/adminMethods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ describe('DullahanPodManager contract tests - Admin functions', () => {

await manager.connect(admin).addCollateral(collat.address, aCollat.address)

await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
const podList = await manager.getAllPods()
pod = MockPod__factory.connect(podList[podList.length - 1], provider);

Expand Down Expand Up @@ -763,9 +763,9 @@ describe('DullahanPodManager contract tests - Admin functions', () => {

await manager.connect(admin).addCollateral(collat.address, aCollat.address)

await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
const podList = await manager.getAllPods()
pod = MockPod__factory.connect(podList[podList.length - 3], provider);
pod2 = MockPod__factory.connect(podList[podList.length - 2], provider);
Expand Down Expand Up @@ -821,9 +821,9 @@ describe('DullahanPodManager contract tests - Admin functions', () => {

await manager.connect(admin).addCollateral(collat.address, aCollat.address)

await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
const podList = await manager.getAllPods()
pod = MockPod__factory.connect(podList[podList.length - 3], provider);
pod2 = MockPod__factory.connect(podList[podList.length - 2], provider);
Expand Down
6 changes: 3 additions & 3 deletions test/unit-test/manager/podsMethods.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,9 @@ describe('DullahanPodManager contract tests - Pods only functions', () => {
await manager.connect(admin).addCollateral(collat.address, aCollat.address)
await manager.connect(admin).addCollateral(collat2.address, aCollat2.address)

await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
await manager.connect(podOwner).createPod(collat.address, podOwner.address)
const podList = await manager.getAllPods()
pod = MockPod__factory.connect(podList[podList.length - 3], provider);
pod2 = MockPod__factory.connect(podList[podList.length - 2], provider);
Expand Down
Loading